forked from mirrors/linux
		
	Revert "crypto: GnuPG based MPI lib - additional sources (part 4)"
This reverts commit 7e8dec918e.
RSA verification implementation does not use this code.
James Morris has asked to remove that.
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Requested-by: James Morris <james.l.morris@oracle.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
			
			
This commit is contained in:
		
							parent
							
								
									423b978802
								
							
						
					
					
						commit
						9e235dcaf4
					
				
					 12 changed files with 0 additions and 1404 deletions
				
			
		|  | @ -361,14 +361,6 @@ config MPILIB | ||||||
| 	  It is used to implement RSA digital signature verification, | 	  It is used to implement RSA digital signature verification, | ||||||
| 	  which is used by IMA/EVM digital signature extension. | 	  which is used by IMA/EVM digital signature extension. | ||||||
| 
 | 
 | ||||||
| config MPILIB_EXTRA |  | ||||||
| 	bool |  | ||||||
| 	depends on MPILIB |  | ||||||
| 	help |  | ||||||
| 	  Additional sources of multiprecision maths library from GnuPG. |  | ||||||
| 	  This code is unnecessary for RSA digital signature verification, |  | ||||||
| 	  but can be compiled if needed. |  | ||||||
| 
 |  | ||||||
| config SIGNATURE | config SIGNATURE | ||||||
| 	tristate | 	tristate | ||||||
| 	depends on KEYS && CRYPTO | 	depends on KEYS && CRYPTO | ||||||
|  |  | ||||||
|  | @ -19,14 +19,3 @@ mpi-y = \ | ||||||
| 	mpih-mul.o			\
 | 	mpih-mul.o			\
 | ||||||
| 	mpi-pow.o			\
 | 	mpi-pow.o			\
 | ||||||
| 	mpiutil.o | 	mpiutil.o | ||||||
| 
 |  | ||||||
| mpi-$(CONFIG_MPILIB_EXTRA) += \
 |  | ||||||
| 	mpi-add.o			\
 |  | ||||||
| 	mpi-div.o			\
 |  | ||||||
| 	mpi-cmp.o			\
 |  | ||||||
| 	mpi-gcd.o			\
 |  | ||||||
| 	mpi-inline.o			\
 |  | ||||||
| 	mpi-inv.o			\
 |  | ||||||
| 	mpi-mpow.o			\
 |  | ||||||
| 	mpi-mul.o			\
 |  | ||||||
| 	mpi-scan.o |  | ||||||
|  |  | ||||||
|  | @ -1,4 +0,0 @@ | ||||||
| /* This file defines some basic constants for the MPI machinery.  We
 |  | ||||||
|  * need to define the types on a per-CPU basis, so it is done with |  | ||||||
|  * this file here.  */ |  | ||||||
| #define BYTES_PER_MPI_LIMB  (SIZEOF_UNSIGNED_LONG) |  | ||||||
|  | @ -1,234 +0,0 @@ | ||||||
| /* mpi-add.c  -  MPI functions
 |  | ||||||
|  *	Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |  | ||||||
|  *	Copyright (C) 1994, 1996 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  * |  | ||||||
|  * Note: This code is heavily based on the GNU MP Library. |  | ||||||
|  *	 Actually it's the same code with only minor changes in the |  | ||||||
|  *	 way the data is stored; this is to support the abstraction |  | ||||||
|  *	 of an optional secure memory allocation which may be used |  | ||||||
|  *	 to avoid revealing of sensitive data due to paging etc. |  | ||||||
|  *	 The GNU MP Library itself is published under the LGPL; |  | ||||||
|  *	 however I decided to publish this code under the plain GPL. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Add the unsigned integer V to the mpi-integer U and store the |  | ||||||
|  * result in W. U and V may be the same. |  | ||||||
|  */ |  | ||||||
| int mpi_add_ui(MPI w, const MPI u, unsigned long v) |  | ||||||
| { |  | ||||||
| 	mpi_ptr_t wp, up; |  | ||||||
| 	mpi_size_t usize, wsize; |  | ||||||
| 	int usign, wsign; |  | ||||||
| 
 |  | ||||||
| 	usize = u->nlimbs; |  | ||||||
| 	usign = u->sign; |  | ||||||
| 	wsign = 0; |  | ||||||
| 
 |  | ||||||
| 	/* If not space for W (and possible carry), increase space.  */ |  | ||||||
| 	wsize = usize + 1; |  | ||||||
| 	if (w->alloced < wsize) |  | ||||||
| 		if (mpi_resize(w, wsize) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 
 |  | ||||||
| 	/* These must be after realloc (U may be the same as W).  */ |  | ||||||
| 	up = u->d; |  | ||||||
| 	wp = w->d; |  | ||||||
| 
 |  | ||||||
| 	if (!usize) {		/* simple */ |  | ||||||
| 		wp[0] = v; |  | ||||||
| 		wsize = v ? 1 : 0; |  | ||||||
| 	} else if (!usign) {	/* mpi is not negative */ |  | ||||||
| 		mpi_limb_t cy; |  | ||||||
| 		cy = mpihelp_add_1(wp, up, usize, v); |  | ||||||
| 		wp[usize] = cy; |  | ||||||
| 		wsize = usize + cy; |  | ||||||
| 	} else {		/* The signs are different.  Need exact comparison to determine
 |  | ||||||
| 				 * which operand to subtract from which.  */ |  | ||||||
| 		if (usize == 1 && up[0] < v) { |  | ||||||
| 			wp[0] = v - up[0]; |  | ||||||
| 			wsize = 1; |  | ||||||
| 		} else { |  | ||||||
| 			mpihelp_sub_1(wp, up, usize, v); |  | ||||||
| 			/* Size can decrease with at most one limb. */ |  | ||||||
| 			wsize = usize - (wp[usize - 1] == 0); |  | ||||||
| 			wsign = 1; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	w->nlimbs = wsize; |  | ||||||
| 	w->sign = wsign; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_add(MPI w, MPI u, MPI v) |  | ||||||
| { |  | ||||||
| 	mpi_ptr_t wp, up, vp; |  | ||||||
| 	mpi_size_t usize, vsize, wsize; |  | ||||||
| 	int usign, vsign, wsign; |  | ||||||
| 
 |  | ||||||
| 	if (u->nlimbs < v->nlimbs) {	/* Swap U and V. */ |  | ||||||
| 		usize = v->nlimbs; |  | ||||||
| 		usign = v->sign; |  | ||||||
| 		vsize = u->nlimbs; |  | ||||||
| 		vsign = u->sign; |  | ||||||
| 		wsize = usize + 1; |  | ||||||
| 		if (RESIZE_IF_NEEDED(w, wsize) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 		/* These must be after realloc (u or v may be the same as w).  */ |  | ||||||
| 		up = v->d; |  | ||||||
| 		vp = u->d; |  | ||||||
| 	} else { |  | ||||||
| 		usize = u->nlimbs; |  | ||||||
| 		usign = u->sign; |  | ||||||
| 		vsize = v->nlimbs; |  | ||||||
| 		vsign = v->sign; |  | ||||||
| 		wsize = usize + 1; |  | ||||||
| 		if (RESIZE_IF_NEEDED(w, wsize) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 		/* These must be after realloc (u or v may be the same as w).  */ |  | ||||||
| 		up = u->d; |  | ||||||
| 		vp = v->d; |  | ||||||
| 	} |  | ||||||
| 	wp = w->d; |  | ||||||
| 	wsign = 0; |  | ||||||
| 
 |  | ||||||
| 	if (!vsize) {		/* simple */ |  | ||||||
| 		MPN_COPY(wp, up, usize); |  | ||||||
| 		wsize = usize; |  | ||||||
| 		wsign = usign; |  | ||||||
| 	} else if (usign != vsign) {	/* different sign */ |  | ||||||
| 		/* This test is right since USIZE >= VSIZE */ |  | ||||||
| 		if (usize != vsize) { |  | ||||||
| 			mpihelp_sub(wp, up, usize, vp, vsize); |  | ||||||
| 			wsize = usize; |  | ||||||
| 			MPN_NORMALIZE(wp, wsize); |  | ||||||
| 			wsign = usign; |  | ||||||
| 		} else if (mpihelp_cmp(up, vp, usize) < 0) { |  | ||||||
| 			mpihelp_sub_n(wp, vp, up, usize); |  | ||||||
| 			wsize = usize; |  | ||||||
| 			MPN_NORMALIZE(wp, wsize); |  | ||||||
| 			if (!usign) |  | ||||||
| 				wsign = 1; |  | ||||||
| 		} else { |  | ||||||
| 			mpihelp_sub_n(wp, up, vp, usize); |  | ||||||
| 			wsize = usize; |  | ||||||
| 			MPN_NORMALIZE(wp, wsize); |  | ||||||
| 			if (usign) |  | ||||||
| 				wsign = 1; |  | ||||||
| 		} |  | ||||||
| 	} else {		/* U and V have same sign. Add them. */ |  | ||||||
| 		mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize); |  | ||||||
| 		wp[usize] = cy; |  | ||||||
| 		wsize = usize + cy; |  | ||||||
| 		if (usign) |  | ||||||
| 			wsign = 1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	w->nlimbs = wsize; |  | ||||||
| 	w->sign = wsign; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Subtract the unsigned integer V from the mpi-integer U and store the |  | ||||||
|  * result in W. |  | ||||||
|  */ |  | ||||||
| int mpi_sub_ui(MPI w, MPI u, unsigned long v) |  | ||||||
| { |  | ||||||
| 	mpi_ptr_t wp, up; |  | ||||||
| 	mpi_size_t usize, wsize; |  | ||||||
| 	int usign, wsign; |  | ||||||
| 
 |  | ||||||
| 	usize = u->nlimbs; |  | ||||||
| 	usign = u->sign; |  | ||||||
| 	wsign = 0; |  | ||||||
| 
 |  | ||||||
| 	/* If not space for W (and possible carry), increase space.  */ |  | ||||||
| 	wsize = usize + 1; |  | ||||||
| 	if (w->alloced < wsize) |  | ||||||
| 		if (mpi_resize(w, wsize) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 
 |  | ||||||
| 	/* These must be after realloc (U may be the same as W).  */ |  | ||||||
| 	up = u->d; |  | ||||||
| 	wp = w->d; |  | ||||||
| 
 |  | ||||||
| 	if (!usize) {		/* simple */ |  | ||||||
| 		wp[0] = v; |  | ||||||
| 		wsize = v ? 1 : 0; |  | ||||||
| 		wsign = 1; |  | ||||||
| 	} else if (usign) {	/* mpi and v are negative */ |  | ||||||
| 		mpi_limb_t cy; |  | ||||||
| 		cy = mpihelp_add_1(wp, up, usize, v); |  | ||||||
| 		wp[usize] = cy; |  | ||||||
| 		wsize = usize + cy; |  | ||||||
| 	} else {		/* The signs are different.  Need exact comparison to determine
 |  | ||||||
| 				 * which operand to subtract from which.  */ |  | ||||||
| 		if (usize == 1 && up[0] < v) { |  | ||||||
| 			wp[0] = v - up[0]; |  | ||||||
| 			wsize = 1; |  | ||||||
| 			wsign = 1; |  | ||||||
| 		} else { |  | ||||||
| 			mpihelp_sub_1(wp, up, usize, v); |  | ||||||
| 			/* Size can decrease with at most one limb. */ |  | ||||||
| 			wsize = usize - (wp[usize - 1] == 0); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	w->nlimbs = wsize; |  | ||||||
| 	w->sign = wsign; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_sub(MPI w, MPI u, MPI v) |  | ||||||
| { |  | ||||||
| 	int rc; |  | ||||||
| 
 |  | ||||||
| 	if (w == v) { |  | ||||||
| 		MPI vv; |  | ||||||
| 		if (mpi_copy(&vv, v) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 		vv->sign = !vv->sign; |  | ||||||
| 		rc = mpi_add(w, u, vv); |  | ||||||
| 		mpi_free(vv); |  | ||||||
| 	} else { |  | ||||||
| 		/* fixme: this is not thread-save (we temp. modify v) */ |  | ||||||
| 		v->sign = !v->sign; |  | ||||||
| 		rc = mpi_add(w, u, v); |  | ||||||
| 		v->sign = !v->sign; |  | ||||||
| 	} |  | ||||||
| 	return rc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_addm(MPI w, MPI u, MPI v, MPI m) |  | ||||||
| { |  | ||||||
| 	if (mpi_add(w, u, v) < 0 || mpi_fdiv_r(w, w, m) < 0) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_subm(MPI w, MPI u, MPI v, MPI m) |  | ||||||
| { |  | ||||||
| 	if (mpi_sub(w, u, v) < 0 || mpi_fdiv_r(w, w, m) < 0) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,68 +0,0 @@ | ||||||
| /* mpi-cmp.c  -  MPI functions
 |  | ||||||
|  * Copyright (C) 1998, 1999 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| 
 |  | ||||||
| int mpi_cmp_ui(MPI u, unsigned long v) |  | ||||||
| { |  | ||||||
| 	mpi_limb_t limb = v; |  | ||||||
| 
 |  | ||||||
| 	mpi_normalize(u); |  | ||||||
| 	if (!u->nlimbs && !limb) |  | ||||||
| 		return 0; |  | ||||||
| 	if (u->sign) |  | ||||||
| 		return -1; |  | ||||||
| 	if (u->nlimbs > 1) |  | ||||||
| 		return 1; |  | ||||||
| 
 |  | ||||||
| 	if (u->d[0] == limb) |  | ||||||
| 		return 0; |  | ||||||
| 	else if (u->d[0] > limb) |  | ||||||
| 		return 1; |  | ||||||
| 	else |  | ||||||
| 		return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_cmp(MPI u, MPI v) |  | ||||||
| { |  | ||||||
| 	mpi_size_t usize, vsize; |  | ||||||
| 	int cmp; |  | ||||||
| 
 |  | ||||||
| 	mpi_normalize(u); |  | ||||||
| 	mpi_normalize(v); |  | ||||||
| 	usize = u->nlimbs; |  | ||||||
| 	vsize = v->nlimbs; |  | ||||||
| 	if (!u->sign && v->sign) |  | ||||||
| 		return 1; |  | ||||||
| 	if (u->sign && !v->sign) |  | ||||||
| 		return -1; |  | ||||||
| 	if (usize != vsize && !u->sign && !v->sign) |  | ||||||
| 		return usize - vsize; |  | ||||||
| 	if (usize != vsize && u->sign && v->sign) |  | ||||||
| 		return vsize + usize; |  | ||||||
| 	if (!usize) |  | ||||||
| 		return 0; |  | ||||||
| 	cmp = mpihelp_cmp(u->d, v->d, usize); |  | ||||||
| 	if (!cmp) |  | ||||||
| 		return 0; |  | ||||||
| 	if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) |  | ||||||
| 		return 1; |  | ||||||
| 	return -1; |  | ||||||
| } |  | ||||||
|  | @ -1,338 +0,0 @@ | ||||||
| /* mpi-div.c  -  MPI functions
 |  | ||||||
|  *	Copyright (C) 1994, 1996 Free Software Foundation, Inc. |  | ||||||
|  *	Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  * |  | ||||||
|  * Note: This code is heavily based on the GNU MP Library. |  | ||||||
|  *	 Actually it's the same code with only minor changes in the |  | ||||||
|  *	 way the data is stored; this is to support the abstraction |  | ||||||
|  *	 of an optional secure memory allocation which may be used |  | ||||||
|  *	 to avoid revealing of sensitive data due to paging etc. |  | ||||||
|  *	 The GNU MP Library itself is published under the LGPL; |  | ||||||
|  *	 however I decided to publish this code under the plain GPL. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include <linux/string.h> |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| #include "longlong.h" |  | ||||||
| 
 |  | ||||||
| int mpi_fdiv_r(MPI rem, MPI dividend, MPI divisor) |  | ||||||
| { |  | ||||||
| 	int rc = -ENOMEM; |  | ||||||
| 	int divisor_sign = divisor->sign; |  | ||||||
| 	MPI temp_divisor = NULL; |  | ||||||
| 
 |  | ||||||
| 	/* We need the original value of the divisor after the remainder has been
 |  | ||||||
| 	 * preliminary calculated.      We have to copy it to temporary space if it's |  | ||||||
| 	 * the same variable as REM.  */ |  | ||||||
| 	if (rem == divisor) { |  | ||||||
| 		if (mpi_copy(&temp_divisor, divisor) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 		divisor = temp_divisor; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (mpi_tdiv_qr(NULL, rem, dividend, divisor) < 0) |  | ||||||
| 		goto nomem; |  | ||||||
| 	if (((divisor_sign ? 1 : 0) ^ (dividend->sign ? 1 : 0)) && rem->nlimbs) |  | ||||||
| 		if (mpi_add(rem, rem, divisor) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 
 |  | ||||||
| 	rc = 0; |  | ||||||
| 
 |  | ||||||
| nomem: |  | ||||||
| 	if (temp_divisor) |  | ||||||
| 		mpi_free(temp_divisor); |  | ||||||
| 	return rc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Division rounding the quotient towards -infinity. |  | ||||||
|  * The remainder gets the same sign as the denominator. |  | ||||||
|  * rem is optional |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| ulong mpi_fdiv_r_ui(MPI rem, MPI dividend, ulong divisor) |  | ||||||
| { |  | ||||||
| 	mpi_limb_t rlimb; |  | ||||||
| 
 |  | ||||||
| 	rlimb = mpihelp_mod_1(dividend->d, dividend->nlimbs, divisor); |  | ||||||
| 	if (rlimb && dividend->sign) |  | ||||||
| 		rlimb = divisor - rlimb; |  | ||||||
| 
 |  | ||||||
| 	if (rem) { |  | ||||||
| 		rem->d[0] = rlimb; |  | ||||||
| 		rem->nlimbs = rlimb ? 1 : 0; |  | ||||||
| 	} |  | ||||||
| 	return rlimb; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_fdiv_q(MPI quot, MPI dividend, MPI divisor) |  | ||||||
| { |  | ||||||
| 	MPI tmp = mpi_alloc(mpi_get_nlimbs(quot)); |  | ||||||
| 	if (!tmp) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 	mpi_fdiv_qr(quot, tmp, dividend, divisor); |  | ||||||
| 	mpi_free(tmp); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_fdiv_qr(MPI quot, MPI rem, MPI dividend, MPI divisor) |  | ||||||
| { |  | ||||||
| 	int divisor_sign = divisor->sign; |  | ||||||
| 	MPI temp_divisor = NULL; |  | ||||||
| 
 |  | ||||||
| 	if (quot == divisor || rem == divisor) { |  | ||||||
| 		if (mpi_copy(&temp_divisor, divisor) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 		divisor = temp_divisor; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (mpi_tdiv_qr(quot, rem, dividend, divisor) < 0) |  | ||||||
| 		goto nomem; |  | ||||||
| 
 |  | ||||||
| 	if ((divisor_sign ^ dividend->sign) && rem->nlimbs) { |  | ||||||
| 		if (mpi_sub_ui(quot, quot, 1) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 		if (mpi_add(rem, rem, divisor) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (temp_divisor) |  | ||||||
| 		mpi_free(temp_divisor); |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| 
 |  | ||||||
| nomem: |  | ||||||
| 	mpi_free(temp_divisor); |  | ||||||
| 	return -ENOMEM; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* If den == quot, den needs temporary storage.
 |  | ||||||
|  * If den == rem, den needs temporary storage. |  | ||||||
|  * If num == quot, num needs temporary storage. |  | ||||||
|  * If den has temporary storage, it can be normalized while being copied, |  | ||||||
|  *   i.e no extra storage should be allocated. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| int mpi_tdiv_r(MPI rem, MPI num, MPI den) |  | ||||||
| { |  | ||||||
| 	return mpi_tdiv_qr(NULL, rem, num, den); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den) |  | ||||||
| { |  | ||||||
| 	int rc = -ENOMEM; |  | ||||||
| 	mpi_ptr_t np, dp; |  | ||||||
| 	mpi_ptr_t qp, rp; |  | ||||||
| 	mpi_size_t nsize = num->nlimbs; |  | ||||||
| 	mpi_size_t dsize = den->nlimbs; |  | ||||||
| 	mpi_size_t qsize, rsize; |  | ||||||
| 	mpi_size_t sign_remainder = num->sign; |  | ||||||
| 	mpi_size_t sign_quotient = num->sign ^ den->sign; |  | ||||||
| 	unsigned normalization_steps; |  | ||||||
| 	mpi_limb_t q_limb; |  | ||||||
| 	mpi_ptr_t marker[5]; |  | ||||||
| 	int markidx = 0; |  | ||||||
| 
 |  | ||||||
| 	if (!dsize) |  | ||||||
| 		return -EINVAL; |  | ||||||
| 
 |  | ||||||
| 	memset(marker, 0, sizeof(marker)); |  | ||||||
| 
 |  | ||||||
| 	/* Ensure space is enough for quotient and remainder.
 |  | ||||||
| 	 * We need space for an extra limb in the remainder, because it's |  | ||||||
| 	 * up-shifted (normalized) below.  */ |  | ||||||
| 	rsize = nsize + 1; |  | ||||||
| 	if (mpi_resize(rem, rsize) < 0) |  | ||||||
| 		goto nomem; |  | ||||||
| 
 |  | ||||||
| 	qsize = rsize - dsize;	/* qsize cannot be bigger than this.  */ |  | ||||||
| 	if (qsize <= 0) { |  | ||||||
| 		if (num != rem) { |  | ||||||
| 			rem->nlimbs = num->nlimbs; |  | ||||||
| 			rem->sign = num->sign; |  | ||||||
| 			MPN_COPY(rem->d, num->d, nsize); |  | ||||||
| 		} |  | ||||||
| 		if (quot) { |  | ||||||
| 			/* This needs to follow the assignment to rem, in case the
 |  | ||||||
| 			 * numerator and quotient are the same.  */ |  | ||||||
| 			quot->nlimbs = 0; |  | ||||||
| 			quot->sign = 0; |  | ||||||
| 		} |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (quot) |  | ||||||
| 		if (mpi_resize(quot, qsize) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 
 |  | ||||||
| 	/* Read pointers here, when reallocation is finished.  */ |  | ||||||
| 	np = num->d; |  | ||||||
| 	dp = den->d; |  | ||||||
| 	rp = rem->d; |  | ||||||
| 
 |  | ||||||
| 	/* Optimize division by a single-limb divisor.  */ |  | ||||||
| 	if (dsize == 1) { |  | ||||||
| 		mpi_limb_t rlimb; |  | ||||||
| 		if (quot) { |  | ||||||
| 			qp = quot->d; |  | ||||||
| 			rlimb = mpihelp_divmod_1(qp, np, nsize, dp[0]); |  | ||||||
| 			qsize -= qp[qsize - 1] == 0; |  | ||||||
| 			quot->nlimbs = qsize; |  | ||||||
| 			quot->sign = sign_quotient; |  | ||||||
| 		} else |  | ||||||
| 			rlimb = mpihelp_mod_1(np, nsize, dp[0]); |  | ||||||
| 		rp[0] = rlimb; |  | ||||||
| 		rsize = rlimb != 0 ? 1 : 0; |  | ||||||
| 		rem->nlimbs = rsize; |  | ||||||
| 		rem->sign = sign_remainder; |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (quot) { |  | ||||||
| 		qp = quot->d; |  | ||||||
| 		/* Make sure QP and NP point to different objects.  Otherwise the
 |  | ||||||
| 		 * numerator would be gradually overwritten by the quotient limbs.  */ |  | ||||||
| 		if (qp == np) {	/* Copy NP object to temporary space.  */ |  | ||||||
| 			np = marker[markidx++] = mpi_alloc_limb_space(nsize); |  | ||||||
| 			if (!np) |  | ||||||
| 				goto nomem; |  | ||||||
| 			MPN_COPY(np, qp, nsize); |  | ||||||
| 		} |  | ||||||
| 	} else			/* Put quotient at top of remainder. */ |  | ||||||
| 		qp = rp + dsize; |  | ||||||
| 
 |  | ||||||
| 	count_leading_zeros(normalization_steps, dp[dsize - 1]); |  | ||||||
| 
 |  | ||||||
| 	/* Normalize the denominator, i.e. make its most significant bit set by
 |  | ||||||
| 	 * shifting it NORMALIZATION_STEPS bits to the left.  Also shift the |  | ||||||
| 	 * numerator the same number of steps (to keep the quotient the same!). |  | ||||||
| 	 */ |  | ||||||
| 	if (normalization_steps) { |  | ||||||
| 		mpi_ptr_t tp; |  | ||||||
| 		mpi_limb_t nlimb; |  | ||||||
| 
 |  | ||||||
| 		/* Shift up the denominator setting the most significant bit of
 |  | ||||||
| 		 * the most significant word.  Use temporary storage not to clobber |  | ||||||
| 		 * the original contents of the denominator.  */ |  | ||||||
| 		tp = marker[markidx++] = mpi_alloc_limb_space(dsize); |  | ||||||
| 		if (!tp) |  | ||||||
| 			goto nomem; |  | ||||||
| 		mpihelp_lshift(tp, dp, dsize, normalization_steps); |  | ||||||
| 		dp = tp; |  | ||||||
| 
 |  | ||||||
| 		/* Shift up the numerator, possibly introducing a new most
 |  | ||||||
| 		 * significant word.  Move the shifted numerator in the remainder |  | ||||||
| 		 * meanwhile.  */ |  | ||||||
| 		nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps); |  | ||||||
| 		if (nlimb) { |  | ||||||
| 			rp[nsize] = nlimb; |  | ||||||
| 			rsize = nsize + 1; |  | ||||||
| 		} else |  | ||||||
| 			rsize = nsize; |  | ||||||
| 	} else { |  | ||||||
| 		/* The denominator is already normalized, as required.  Copy it to
 |  | ||||||
| 		 * temporary space if it overlaps with the quotient or remainder.  */ |  | ||||||
| 		if (dp == rp || (quot && (dp == qp))) { |  | ||||||
| 			mpi_ptr_t tp; |  | ||||||
| 
 |  | ||||||
| 			tp = marker[markidx++] = mpi_alloc_limb_space(dsize); |  | ||||||
| 			if (!tp) |  | ||||||
| 				goto nomem; |  | ||||||
| 			MPN_COPY(tp, dp, dsize); |  | ||||||
| 			dp = tp; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		/* Move the numerator to the remainder.  */ |  | ||||||
| 		if (rp != np) |  | ||||||
| 			MPN_COPY(rp, np, nsize); |  | ||||||
| 
 |  | ||||||
| 		rsize = nsize; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	q_limb = mpihelp_divrem(qp, 0, rp, rsize, dp, dsize); |  | ||||||
| 
 |  | ||||||
| 	if (quot) { |  | ||||||
| 		qsize = rsize - dsize; |  | ||||||
| 		if (q_limb) { |  | ||||||
| 			qp[qsize] = q_limb; |  | ||||||
| 			qsize += 1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		quot->nlimbs = qsize; |  | ||||||
| 		quot->sign = sign_quotient; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	rsize = dsize; |  | ||||||
| 	MPN_NORMALIZE(rp, rsize); |  | ||||||
| 
 |  | ||||||
| 	if (normalization_steps && rsize) { |  | ||||||
| 		mpihelp_rshift(rp, rp, rsize, normalization_steps); |  | ||||||
| 		rsize -= rp[rsize - 1] == 0 ? 1 : 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	rem->nlimbs = rsize; |  | ||||||
| 	rem->sign = sign_remainder; |  | ||||||
| 
 |  | ||||||
| 	rc = 0; |  | ||||||
| nomem: |  | ||||||
| 	while (markidx) |  | ||||||
| 		mpi_free_limb_space(marker[--markidx]); |  | ||||||
| 	return rc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_tdiv_q_2exp(MPI w, MPI u, unsigned count) |  | ||||||
| { |  | ||||||
| 	mpi_size_t usize, wsize; |  | ||||||
| 	mpi_size_t limb_cnt; |  | ||||||
| 
 |  | ||||||
| 	usize = u->nlimbs; |  | ||||||
| 	limb_cnt = count / BITS_PER_MPI_LIMB; |  | ||||||
| 	wsize = usize - limb_cnt; |  | ||||||
| 	if (limb_cnt >= usize) |  | ||||||
| 		w->nlimbs = 0; |  | ||||||
| 	else { |  | ||||||
| 		mpi_ptr_t wp; |  | ||||||
| 		mpi_ptr_t up; |  | ||||||
| 
 |  | ||||||
| 		if (RESIZE_IF_NEEDED(w, wsize) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 		wp = w->d; |  | ||||||
| 		up = u->d; |  | ||||||
| 
 |  | ||||||
| 		count %= BITS_PER_MPI_LIMB; |  | ||||||
| 		if (count) { |  | ||||||
| 			mpihelp_rshift(wp, up + limb_cnt, wsize, count); |  | ||||||
| 			wsize -= !wp[wsize - 1]; |  | ||||||
| 		} else { |  | ||||||
| 			MPN_COPY_INCR(wp, up + limb_cnt, wsize); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		w->nlimbs = wsize; |  | ||||||
| 	} |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Check whether dividend is divisible by divisor |  | ||||||
|  * (note: divisor must fit into a limb) |  | ||||||
|  */ |  | ||||||
| int mpi_divisible_ui(MPI dividend, ulong divisor) |  | ||||||
| { |  | ||||||
| 	return !mpihelp_mod_1(dividend->d, dividend->nlimbs, divisor); |  | ||||||
| } |  | ||||||
|  | @ -1,59 +0,0 @@ | ||||||
| /* mpi-gcd.c  -  MPI functions
 |  | ||||||
|  * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Find the greatest common divisor G of A and B. |  | ||||||
|  * Return: true if this 1, false in all other cases |  | ||||||
|  */ |  | ||||||
| int mpi_gcd(MPI g, const MPI xa, const MPI xb) |  | ||||||
| { |  | ||||||
| 	MPI a = NULL, b = NULL; |  | ||||||
| 
 |  | ||||||
| 	if (mpi_copy(&a, xa) < 0) |  | ||||||
| 		goto nomem; |  | ||||||
| 
 |  | ||||||
| 	if (mpi_copy(&b, xb) < 0) |  | ||||||
| 		goto nomem; |  | ||||||
| 
 |  | ||||||
| 	/* TAOCP Vol II, 4.5.2, Algorithm A */ |  | ||||||
| 	a->sign = 0; |  | ||||||
| 	b->sign = 0; |  | ||||||
| 	while (mpi_cmp_ui(b, 0)) { |  | ||||||
| 		if (mpi_fdiv_r(g, a, b) < 0)	/* g used as temorary variable */ |  | ||||||
| 			goto nomem; |  | ||||||
| 		if (mpi_set(a, b) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 		if (mpi_set(b, g) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 	} |  | ||||||
| 	if (mpi_set(g, a) < 0) |  | ||||||
| 		goto nomem; |  | ||||||
| 
 |  | ||||||
| 	mpi_free(a); |  | ||||||
| 	mpi_free(b); |  | ||||||
| 	return !mpi_cmp_ui(g, 1); |  | ||||||
| 
 |  | ||||||
| nomem: |  | ||||||
| 	mpi_free(a); |  | ||||||
| 	mpi_free(b); |  | ||||||
| 	return -ENOMEM; |  | ||||||
| } |  | ||||||
|  | @ -1,31 +0,0 @@ | ||||||
| /* mpi-inline.c
 |  | ||||||
|  * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| /* put the inline functions as real functions into the lib */ |  | ||||||
| #define G10_MPI_INLINE_DECL |  | ||||||
| 
 |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| 
 |  | ||||||
| /* always include the header becuase it is only
 |  | ||||||
|  * included by mpi-internal if __GCC__ is defined but we |  | ||||||
|  * need it here in all cases and the above definition of |  | ||||||
|  * of the macro allows us to do so |  | ||||||
|  */ |  | ||||||
| #include "mpi-inline.h" |  | ||||||
|  | @ -1,187 +0,0 @@ | ||||||
| /* mpi-inv.c  -  MPI functions
 |  | ||||||
|  * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Calculate the multiplicative inverse X of A mod N |  | ||||||
|  * That is: Find the solution x for |  | ||||||
|  *		1 = (a*x) mod n |  | ||||||
|  */ |  | ||||||
| int mpi_invm(MPI x, const MPI a, const MPI n) |  | ||||||
| { |  | ||||||
| 	/* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
 |  | ||||||
| 	 * modified according to Michael Penk's solution for Exercice 35 |  | ||||||
| 	 * with further enhancement */ |  | ||||||
| 	MPI u = NULL, v = NULL; |  | ||||||
| 	MPI u1 = NULL, u2 = NULL, u3 = NULL; |  | ||||||
| 	MPI v1 = NULL, v2 = NULL, v3 = NULL; |  | ||||||
| 	MPI t1 = NULL, t2 = NULL, t3 = NULL; |  | ||||||
| 	unsigned k; |  | ||||||
| 	int sign; |  | ||||||
| 	int odd = 0; |  | ||||||
| 	int rc = -ENOMEM; |  | ||||||
| 
 |  | ||||||
| 	if (mpi_copy(&u, a) < 0) |  | ||||||
| 		goto cleanup; |  | ||||||
| 	if (mpi_copy(&v, n) < 0) |  | ||||||
| 		goto cleanup; |  | ||||||
| 
 |  | ||||||
| 	for (k = 0; !mpi_test_bit(u, 0) && !mpi_test_bit(v, 0); k++) { |  | ||||||
| 		if (mpi_rshift(u, u, 1) < 0) |  | ||||||
| 			goto cleanup; |  | ||||||
| 		if (mpi_rshift(v, v, 1) < 0) |  | ||||||
| 			goto cleanup; |  | ||||||
| 	} |  | ||||||
| 	odd = mpi_test_bit(v, 0); |  | ||||||
| 
 |  | ||||||
| 	u1 = mpi_alloc_set_ui(1); |  | ||||||
| 	if (!u1) |  | ||||||
| 		goto cleanup; |  | ||||||
| 	if (!odd) { |  | ||||||
| 		u2 = mpi_alloc_set_ui(0); |  | ||||||
| 		if (!u2) |  | ||||||
| 			goto cleanup; |  | ||||||
| 	} |  | ||||||
| 	if (mpi_copy(&u3, u) < 0) |  | ||||||
| 		goto cleanup; |  | ||||||
| 	if (mpi_copy(&v1, v) < 0) |  | ||||||
| 		goto cleanup; |  | ||||||
| 	if (!odd) { |  | ||||||
| 		v2 = mpi_alloc(mpi_get_nlimbs(u)); |  | ||||||
| 		if (!v2) |  | ||||||
| 			goto cleanup; |  | ||||||
| 		if (mpi_sub(v2, u1, u) < 0) |  | ||||||
| 			goto cleanup;	/* U is used as const 1 */ |  | ||||||
| 	} |  | ||||||
| 	if (mpi_copy(&v3, v) < 0) |  | ||||||
| 		goto cleanup; |  | ||||||
| 	if (mpi_test_bit(u, 0)) {	/* u is odd */ |  | ||||||
| 		t1 = mpi_alloc_set_ui(0); |  | ||||||
| 		if (!t1) |  | ||||||
| 			goto cleanup; |  | ||||||
| 		if (!odd) { |  | ||||||
| 			t2 = mpi_alloc_set_ui(1); |  | ||||||
| 			if (!t2) |  | ||||||
| 				goto cleanup; |  | ||||||
| 			t2->sign = 1; |  | ||||||
| 		} |  | ||||||
| 		if (mpi_copy(&t3, v) < 0) |  | ||||||
| 			goto cleanup; |  | ||||||
| 		t3->sign = !t3->sign; |  | ||||||
| 		goto Y4; |  | ||||||
| 	} else { |  | ||||||
| 		t1 = mpi_alloc_set_ui(1); |  | ||||||
| 		if (!t1) |  | ||||||
| 			goto cleanup; |  | ||||||
| 		if (!odd) { |  | ||||||
| 			t2 = mpi_alloc_set_ui(0); |  | ||||||
| 			if (!t2) |  | ||||||
| 				goto cleanup; |  | ||||||
| 		} |  | ||||||
| 		if (mpi_copy(&t3, u) < 0) |  | ||||||
| 			goto cleanup; |  | ||||||
| 	} |  | ||||||
| 	do { |  | ||||||
| 		do { |  | ||||||
| 			if (!odd) { |  | ||||||
| 				if (mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0)) {	/* one is odd */ |  | ||||||
| 					if (mpi_add(t1, t1, v) < 0) |  | ||||||
| 						goto cleanup; |  | ||||||
| 					if (mpi_sub(t2, t2, u) < 0) |  | ||||||
| 						goto cleanup; |  | ||||||
| 				} |  | ||||||
| 				if (mpi_rshift(t1, t1, 1) < 0) |  | ||||||
| 					goto cleanup; |  | ||||||
| 				if (mpi_rshift(t2, t2, 1) < 0) |  | ||||||
| 					goto cleanup; |  | ||||||
| 				if (mpi_rshift(t3, t3, 1) < 0) |  | ||||||
| 					goto cleanup; |  | ||||||
| 			} else { |  | ||||||
| 				if (mpi_test_bit(t1, 0)) |  | ||||||
| 					if (mpi_add(t1, t1, v) < 0) |  | ||||||
| 						goto cleanup; |  | ||||||
| 				if (mpi_rshift(t1, t1, 1) < 0) |  | ||||||
| 					goto cleanup; |  | ||||||
| 				if (mpi_rshift(t3, t3, 1) < 0) |  | ||||||
| 					goto cleanup; |  | ||||||
| 			} |  | ||||||
| Y4: |  | ||||||
| 			; |  | ||||||
| 		} while (!mpi_test_bit(t3, 0));	/* while t3 is even */ |  | ||||||
| 
 |  | ||||||
| 		if (!t3->sign) { |  | ||||||
| 			if (mpi_set(u1, t1) < 0) |  | ||||||
| 				goto cleanup; |  | ||||||
| 			if (!odd) |  | ||||||
| 				if (mpi_set(u2, t2) < 0) |  | ||||||
| 					goto cleanup; |  | ||||||
| 			if (mpi_set(u3, t3) < 0) |  | ||||||
| 				goto cleanup; |  | ||||||
| 		} else { |  | ||||||
| 			if (mpi_sub(v1, v, t1) < 0) |  | ||||||
| 				goto cleanup; |  | ||||||
| 			sign = u->sign; |  | ||||||
| 			u->sign = !u->sign; |  | ||||||
| 			if (!odd) |  | ||||||
| 				if (mpi_sub(v2, u, t2) < 0) |  | ||||||
| 					goto cleanup; |  | ||||||
| 			u->sign = sign; |  | ||||||
| 			sign = t3->sign; |  | ||||||
| 			t3->sign = !t3->sign; |  | ||||||
| 			if (mpi_set(v3, t3) < 0) |  | ||||||
| 				goto cleanup; |  | ||||||
| 			t3->sign = sign; |  | ||||||
| 		} |  | ||||||
| 		if (mpi_sub(t1, u1, v1) < 0) |  | ||||||
| 			goto cleanup; |  | ||||||
| 		if (!odd) |  | ||||||
| 			if (mpi_sub(t2, u2, v2) < 0) |  | ||||||
| 				goto cleanup; |  | ||||||
| 		if (mpi_sub(t3, u3, v3) < 0) |  | ||||||
| 			goto cleanup; |  | ||||||
| 		if (t1->sign) { |  | ||||||
| 			if (mpi_add(t1, t1, v) < 0) |  | ||||||
| 				goto cleanup; |  | ||||||
| 			if (!odd) |  | ||||||
| 				if (mpi_sub(t2, t2, u) < 0) |  | ||||||
| 					goto cleanup; |  | ||||||
| 		} |  | ||||||
| 	} while (mpi_cmp_ui(t3, 0));	/* while t3 != 0 */ |  | ||||||
| 	/* mpi_lshift( u3, k ); */ |  | ||||||
| 	rc = mpi_set(x, u1); |  | ||||||
| 
 |  | ||||||
| cleanup: |  | ||||||
| 	mpi_free(u1); |  | ||||||
| 	mpi_free(v1); |  | ||||||
| 	mpi_free(t1); |  | ||||||
| 	if (!odd) { |  | ||||||
| 		mpi_free(u2); |  | ||||||
| 		mpi_free(v2); |  | ||||||
| 		mpi_free(t2); |  | ||||||
| 	} |  | ||||||
| 	mpi_free(u3); |  | ||||||
| 	mpi_free(v3); |  | ||||||
| 	mpi_free(t3); |  | ||||||
| 
 |  | ||||||
| 	mpi_free(u); |  | ||||||
| 	mpi_free(v); |  | ||||||
| 	return rc; |  | ||||||
| } |  | ||||||
|  | @ -1,134 +0,0 @@ | ||||||
| /* mpi-mpow.c  -  MPI functions
 |  | ||||||
|  * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| #include "longlong.h" |  | ||||||
| 
 |  | ||||||
| static int build_index(const MPI *exparray, int k, int i, int t) |  | ||||||
| { |  | ||||||
| 	int j, bitno; |  | ||||||
| 	int index = 0; |  | ||||||
| 
 |  | ||||||
| 	bitno = t - i; |  | ||||||
| 	for (j = k - 1; j >= 0; j--) { |  | ||||||
| 		index <<= 1; |  | ||||||
| 		if (mpi_test_bit(exparray[j], bitno)) |  | ||||||
| 			index |= 1; |  | ||||||
| 	} |  | ||||||
| 	return index; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * RES = (BASE[0] ^ EXP[0]) *  (BASE[1] ^ EXP[1]) * ... * mod M |  | ||||||
|  */ |  | ||||||
| int mpi_mulpowm(MPI res, MPI *basearray, MPI *exparray, MPI m) |  | ||||||
| { |  | ||||||
| 	int rc = -ENOMEM; |  | ||||||
| 	int k;			/* number of elements */ |  | ||||||
| 	int t;			/* bit size of largest exponent */ |  | ||||||
| 	int i, j, idx; |  | ||||||
| 	MPI *G = NULL;		/* table with precomputed values of size 2^k */ |  | ||||||
| 	MPI tmp = NULL; |  | ||||||
| 
 |  | ||||||
| 	for (k = 0; basearray[k]; k++) |  | ||||||
| 		; |  | ||||||
| 	if (!k) { |  | ||||||
| 		pr_emerg("mpi_mulpowm: assert(k) failed\n"); |  | ||||||
| 		BUG(); |  | ||||||
| 	} |  | ||||||
| 	for (t = 0, i = 0; (tmp = exparray[i]); i++) { |  | ||||||
| 		j = mpi_get_nbits(tmp); |  | ||||||
| 		if (j > t) |  | ||||||
| 			t = j; |  | ||||||
| 	} |  | ||||||
| 	if (i != k) { |  | ||||||
| 		pr_emerg("mpi_mulpowm: assert(i==k) failed\n"); |  | ||||||
| 		BUG(); |  | ||||||
| 	} |  | ||||||
| 	if (!t) { |  | ||||||
| 		pr_emerg("mpi_mulpowm: assert(t) failed\n"); |  | ||||||
| 		BUG(); |  | ||||||
| 	} |  | ||||||
| 	if (k >= 10) { |  | ||||||
| 		pr_emerg("mpi_mulpowm: assert(k<10) failed\n"); |  | ||||||
| 		BUG(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	G = kzalloc((1 << k) * sizeof *G, GFP_KERNEL); |  | ||||||
| 	if (!G) |  | ||||||
| 		goto err_out; |  | ||||||
| 
 |  | ||||||
| 	/* and calculate */ |  | ||||||
| 	tmp = mpi_alloc(mpi_get_nlimbs(m) + 1); |  | ||||||
| 	if (!tmp) |  | ||||||
| 		goto nomem; |  | ||||||
| 	if (mpi_set_ui(res, 1) < 0) |  | ||||||
| 		goto nomem; |  | ||||||
| 	for (i = 1; i <= t; i++) { |  | ||||||
| 		if (mpi_mulm(tmp, res, res, m) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 		idx = build_index(exparray, k, i, t); |  | ||||||
| 		if (!(idx >= 0 && idx < (1 << k))) { |  | ||||||
| 			pr_emerg("mpi_mulpowm: assert(idx >= 0 && idx < (1<<k)) failed\n"); |  | ||||||
| 			BUG(); |  | ||||||
| 		} |  | ||||||
| 		if (!G[idx]) { |  | ||||||
| 			if (!idx) { |  | ||||||
| 				G[0] = mpi_alloc_set_ui(1); |  | ||||||
| 				if (!G[0]) |  | ||||||
| 					goto nomem; |  | ||||||
| 			} else { |  | ||||||
| 				for (j = 0; j < k; j++) { |  | ||||||
| 					if ((idx & (1 << j))) { |  | ||||||
| 						if (!G[idx]) { |  | ||||||
| 							if (mpi_copy |  | ||||||
| 							    (&G[idx], |  | ||||||
| 							     basearray[j]) < 0) |  | ||||||
| 								goto nomem; |  | ||||||
| 						} else { |  | ||||||
| 							if (mpi_mulm |  | ||||||
| 							    (G[idx], G[idx], |  | ||||||
| 							     basearray[j], |  | ||||||
| 							     m) < 0) |  | ||||||
| 								goto nomem; |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				if (!G[idx]) { |  | ||||||
| 					G[idx] = mpi_alloc(0); |  | ||||||
| 					if (!G[idx]) |  | ||||||
| 						goto nomem; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if (mpi_mulm(res, tmp, G[idx], m) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	rc = 0; |  | ||||||
| nomem: |  | ||||||
| 	/* cleanup */ |  | ||||||
| 	mpi_free(tmp); |  | ||||||
| 	for (i = 0; i < (1 << k); i++) |  | ||||||
| 		mpi_free(G[i]); |  | ||||||
| 	kfree(G); |  | ||||||
| err_out: |  | ||||||
| 	return rc; |  | ||||||
| } |  | ||||||
|  | @ -1,194 +0,0 @@ | ||||||
| /* mpi-mul.c  -  MPI functions
 |  | ||||||
|  *	Copyright (C) 1994, 1996 Free Software Foundation, Inc. |  | ||||||
|  *	Copyright (C) 1998, 2001 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  * |  | ||||||
|  * Note: This code is heavily based on the GNU MP Library. |  | ||||||
|  *	 Actually it's the same code with only minor changes in the |  | ||||||
|  *	 way the data is stored; this is to support the abstraction |  | ||||||
|  *	 of an optional secure memory allocation which may be used |  | ||||||
|  *	 to avoid revealing of sensitive data due to paging etc. |  | ||||||
|  *	 The GNU MP Library itself is published under the LGPL; |  | ||||||
|  *	 however I decided to publish this code under the plain GPL. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| 
 |  | ||||||
| int mpi_mul_ui(MPI prod, MPI mult, unsigned long small_mult) |  | ||||||
| { |  | ||||||
| 	mpi_size_t size, prod_size; |  | ||||||
| 	mpi_ptr_t prod_ptr; |  | ||||||
| 	mpi_limb_t cy; |  | ||||||
| 	int sign; |  | ||||||
| 
 |  | ||||||
| 	size = mult->nlimbs; |  | ||||||
| 	sign = mult->sign; |  | ||||||
| 
 |  | ||||||
| 	if (!size || !small_mult) { |  | ||||||
| 		prod->nlimbs = 0; |  | ||||||
| 		prod->sign = 0; |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	prod_size = size + 1; |  | ||||||
| 	if (prod->alloced < prod_size) |  | ||||||
| 		if (mpi_resize(prod, prod_size) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 	prod_ptr = prod->d; |  | ||||||
| 
 |  | ||||||
| 	cy = mpihelp_mul_1(prod_ptr, mult->d, size, (mpi_limb_t) small_mult); |  | ||||||
| 	if (cy) |  | ||||||
| 		prod_ptr[size++] = cy; |  | ||||||
| 	prod->nlimbs = size; |  | ||||||
| 	prod->sign = sign; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_mul_2exp(MPI w, MPI u, unsigned long cnt) |  | ||||||
| { |  | ||||||
| 	mpi_size_t usize, wsize, limb_cnt; |  | ||||||
| 	mpi_ptr_t wp; |  | ||||||
| 	mpi_limb_t wlimb; |  | ||||||
| 	int usign, wsign; |  | ||||||
| 
 |  | ||||||
| 	usize = u->nlimbs; |  | ||||||
| 	usign = u->sign; |  | ||||||
| 
 |  | ||||||
| 	if (!usize) { |  | ||||||
| 		w->nlimbs = 0; |  | ||||||
| 		w->sign = 0; |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	limb_cnt = cnt / BITS_PER_MPI_LIMB; |  | ||||||
| 	wsize = usize + limb_cnt + 1; |  | ||||||
| 	if (w->alloced < wsize) |  | ||||||
| 		if (mpi_resize(w, wsize) < 0) |  | ||||||
| 			return -ENOMEM; |  | ||||||
| 	wp = w->d; |  | ||||||
| 	wsize = usize + limb_cnt; |  | ||||||
| 	wsign = usign; |  | ||||||
| 
 |  | ||||||
| 	cnt %= BITS_PER_MPI_LIMB; |  | ||||||
| 	if (cnt) { |  | ||||||
| 		wlimb = mpihelp_lshift(wp + limb_cnt, u->d, usize, cnt); |  | ||||||
| 		if (wlimb) { |  | ||||||
| 			wp[wsize] = wlimb; |  | ||||||
| 			wsize++; |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		MPN_COPY_DECR(wp + limb_cnt, u->d, usize); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* Zero all whole limbs at low end.  Do it here and not before calling
 |  | ||||||
| 	 * mpn_lshift, not to lose for U == W.  */ |  | ||||||
| 	MPN_ZERO(wp, limb_cnt); |  | ||||||
| 
 |  | ||||||
| 	w->nlimbs = wsize; |  | ||||||
| 	w->sign = wsign; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_mul(MPI w, MPI u, MPI v) |  | ||||||
| { |  | ||||||
| 	int rc = -ENOMEM; |  | ||||||
| 	mpi_size_t usize, vsize, wsize; |  | ||||||
| 	mpi_ptr_t up, vp, wp; |  | ||||||
| 	mpi_limb_t cy; |  | ||||||
| 	int usign, vsign, sign_product; |  | ||||||
| 	int assign_wp = 0; |  | ||||||
| 	mpi_ptr_t tmp_limb = NULL; |  | ||||||
| 
 |  | ||||||
| 	if (u->nlimbs < v->nlimbs) {	/* Swap U and V. */ |  | ||||||
| 		usize = v->nlimbs; |  | ||||||
| 		usign = v->sign; |  | ||||||
| 		up = v->d; |  | ||||||
| 		vsize = u->nlimbs; |  | ||||||
| 		vsign = u->sign; |  | ||||||
| 		vp = u->d; |  | ||||||
| 	} else { |  | ||||||
| 		usize = u->nlimbs; |  | ||||||
| 		usign = u->sign; |  | ||||||
| 		up = u->d; |  | ||||||
| 		vsize = v->nlimbs; |  | ||||||
| 		vsign = v->sign; |  | ||||||
| 		vp = v->d; |  | ||||||
| 	} |  | ||||||
| 	sign_product = usign ^ vsign; |  | ||||||
| 	wp = w->d; |  | ||||||
| 
 |  | ||||||
| 	/* Ensure W has space enough to store the result.  */ |  | ||||||
| 	wsize = usize + vsize; |  | ||||||
| 	if (w->alloced < (size_t) wsize) { |  | ||||||
| 		if (wp == up || wp == vp) { |  | ||||||
| 			wp = mpi_alloc_limb_space(wsize); |  | ||||||
| 			if (!wp) |  | ||||||
| 				goto nomem; |  | ||||||
| 			assign_wp = 1; |  | ||||||
| 		} else { |  | ||||||
| 			if (mpi_resize(w, wsize) < 0) |  | ||||||
| 				goto nomem; |  | ||||||
| 			wp = w->d; |  | ||||||
| 		} |  | ||||||
| 	} else {		/* Make U and V not overlap with W.      */ |  | ||||||
| 		if (wp == up) { |  | ||||||
| 			/* W and U are identical.  Allocate temporary space for U.      */ |  | ||||||
| 			up = tmp_limb = mpi_alloc_limb_space(usize); |  | ||||||
| 			if (!up) |  | ||||||
| 				goto nomem; |  | ||||||
| 			/* Is V identical too?  Keep it identical with U.  */ |  | ||||||
| 			if (wp == vp) |  | ||||||
| 				vp = up; |  | ||||||
| 			/* Copy to the temporary space.  */ |  | ||||||
| 			MPN_COPY(up, wp, usize); |  | ||||||
| 		} else if (wp == vp) { |  | ||||||
| 			/* W and V are identical.  Allocate temporary space for V.      */ |  | ||||||
| 			vp = tmp_limb = mpi_alloc_limb_space(vsize); |  | ||||||
| 			if (!vp) |  | ||||||
| 				goto nomem; |  | ||||||
| 			/* Copy to the temporary space.  */ |  | ||||||
| 			MPN_COPY(vp, wp, vsize); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!vsize) |  | ||||||
| 		wsize = 0; |  | ||||||
| 	else { |  | ||||||
| 		if (mpihelp_mul(wp, up, usize, vp, vsize, &cy) < 0) |  | ||||||
| 			goto nomem; |  | ||||||
| 		wsize -= cy ? 0 : 1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (assign_wp) |  | ||||||
| 		mpi_assign_limb_space(w, wp, wsize); |  | ||||||
| 
 |  | ||||||
| 	w->nlimbs = wsize; |  | ||||||
| 	w->sign = sign_product; |  | ||||||
| 	rc = 0; |  | ||||||
| nomem: |  | ||||||
| 	if (tmp_limb) |  | ||||||
| 		mpi_free_limb_space(tmp_limb); |  | ||||||
| 	return rc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mpi_mulm(MPI w, MPI u, MPI v, MPI m) |  | ||||||
| { |  | ||||||
| 	if (mpi_mul(w, u, v) < 0) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 	return mpi_fdiv_r(w, w, m); |  | ||||||
| } |  | ||||||
|  | @ -1,136 +0,0 @@ | ||||||
| /* mpi-scan.c  -  MPI functions
 |  | ||||||
|  * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |  | ||||||
|  * |  | ||||||
|  * This file is part of GnuPG. |  | ||||||
|  * |  | ||||||
|  * GnuPG is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * GnuPG is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "mpi-internal.h" |  | ||||||
| #include "longlong.h" |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Scan through an mpi and return byte for byte. a -1 is returned to indicate |  | ||||||
|  * the end of the mpi. Scanning is done from the lsb to the msb, returned |  | ||||||
|  * values are in the range of 0 .. 255. |  | ||||||
|  * |  | ||||||
|  * FIXME: This code is VERY ugly! |  | ||||||
|  */ |  | ||||||
| int mpi_getbyte(const MPI a, unsigned idx) |  | ||||||
| { |  | ||||||
| 	int i, j; |  | ||||||
| 	unsigned n; |  | ||||||
| 	mpi_ptr_t ap; |  | ||||||
| 	mpi_limb_t limb; |  | ||||||
| 
 |  | ||||||
| 	ap = a->d; |  | ||||||
| 	for (n = 0, i = 0; i < a->nlimbs; i++) { |  | ||||||
| 		limb = ap[i]; |  | ||||||
| 		for (j = 0; j < BYTES_PER_MPI_LIMB; j++, n++) |  | ||||||
| 			if (n == idx) |  | ||||||
| 				return (limb >> j * 8) & 0xff; |  | ||||||
| 	} |  | ||||||
| 	return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Put a value at position IDX into A. idx counts from lsb to msb |  | ||||||
|  */ |  | ||||||
| void mpi_putbyte(MPI a, unsigned idx, int xc) |  | ||||||
| { |  | ||||||
| 	int i, j; |  | ||||||
| 	unsigned n; |  | ||||||
| 	mpi_ptr_t ap; |  | ||||||
| 	mpi_limb_t limb, c; |  | ||||||
| 
 |  | ||||||
| 	c = xc & 0xff; |  | ||||||
| 	ap = a->d; |  | ||||||
| 	for (n = 0, i = 0; i < a->alloced; i++) { |  | ||||||
| 		limb = ap[i]; |  | ||||||
| 		for (j = 0; j < BYTES_PER_MPI_LIMB; j++, n++) |  | ||||||
| 			if (n == idx) { |  | ||||||
| #if BYTES_PER_MPI_LIMB == 4 |  | ||||||
| 				if (j == 0) |  | ||||||
| 					limb = (limb & 0xffffff00) | c; |  | ||||||
| 				else if (j == 1) |  | ||||||
| 					limb = (limb & 0xffff00ff) | (c << 8); |  | ||||||
| 				else if (j == 2) |  | ||||||
| 					limb = (limb & 0xff00ffff) | (c << 16); |  | ||||||
| 				else |  | ||||||
| 					limb = (limb & 0x00ffffff) | (c << 24); |  | ||||||
| #elif BYTES_PER_MPI_LIMB == 8 |  | ||||||
| 				if (j == 0) |  | ||||||
| 					limb = (limb & 0xffffffffffffff00) | c; |  | ||||||
| 				else if (j == 1) |  | ||||||
| 					limb = |  | ||||||
| 					    (limb & 0xffffffffffff00ff) | (c << |  | ||||||
| 									   8); |  | ||||||
| 				else if (j == 2) |  | ||||||
| 					limb = |  | ||||||
| 					    (limb & 0xffffffffff00ffff) | (c << |  | ||||||
| 									   16); |  | ||||||
| 				else if (j == 3) |  | ||||||
| 					limb = |  | ||||||
| 					    (limb & 0xffffffff00ffffff) | (c << |  | ||||||
| 									   24); |  | ||||||
| 				else if (j == 4) |  | ||||||
| 					limb = |  | ||||||
| 					    (limb & 0xffffff00ffffffff) | (c << |  | ||||||
| 									   32); |  | ||||||
| 				else if (j == 5) |  | ||||||
| 					limb = |  | ||||||
| 					    (limb & 0xffff00ffffffffff) | (c << |  | ||||||
| 									   40); |  | ||||||
| 				else if (j == 6) |  | ||||||
| 					limb = |  | ||||||
| 					    (limb & 0xff00ffffffffffff) | (c << |  | ||||||
| 									   48); |  | ||||||
| 				else |  | ||||||
| 					limb = |  | ||||||
| 					    (limb & 0x00ffffffffffffff) | (c << |  | ||||||
| 									   56); |  | ||||||
| #else |  | ||||||
| #error please enhance this function, its ugly - i know. |  | ||||||
| #endif |  | ||||||
| 				if (a->nlimbs <= i) |  | ||||||
| 					a->nlimbs = i + 1; |  | ||||||
| 				ap[i] = limb; |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 	} |  | ||||||
| 	log_bug("index out of range\n"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /****************
 |  | ||||||
|  * Count the number of zerobits at the low end of A |  | ||||||
|  */ |  | ||||||
| unsigned mpi_trailing_zeros(const MPI a) |  | ||||||
| { |  | ||||||
| 	unsigned n, count = 0; |  | ||||||
| 
 |  | ||||||
| 	for (n = 0; n < a->nlimbs; n++) { |  | ||||||
| 		if (a->d[n]) { |  | ||||||
| 			unsigned nn; |  | ||||||
| 			mpi_limb_t alimb = a->d[n]; |  | ||||||
| 
 |  | ||||||
| 			count_trailing_zeros(nn, alimb); |  | ||||||
| 			count += nn; |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		count += BITS_PER_MPI_LIMB; |  | ||||||
| 	} |  | ||||||
| 	return count; |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Dmitry Kasatkin
						Dmitry Kasatkin