Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Nothing groundbreaking for this kernel, just cleanups and fixes, and a couple of Smack enhancements." * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (21 commits) Smack: Maintainer Record Smack: don't show empty rules when /smack/load or /smack/load2 is read Smack: user access check bounds Smack: onlycap limits on CAP_MAC_ADMIN Smack: fix smack_new_inode bogosities ima: audit is compiled only when enabled ima: ima_initialized is set only if successful ima: add policy for pseudo fs ima: remove unused cleanup functions ima: free securityfs violations file ima: use full pathnames in measurement list security: Fix nommu build. samples: seccomp: add .gitignore for untracked executables tpm: check the chip reference before using it TPM: fix memleak when register hardware fails TPM: chip disabled state erronously being reported as error MAINTAINERS: TPM maintainers' contacts update Merge branches 'next-queue' and 'next' into next Remove unused code from MPI library Revert "crypto: GnuPG based MPI lib - additional sources (part 4)" ...
This commit is contained in:
		
						commit
						e05644e17e
					
				
							
								
								
									
										16
									
								
								MAINTAINERS
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								MAINTAINERS
									
									
									
									
									
								
							| @ -6230,6 +6230,15 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git | ||||
| F:	include/linux/srcu* | ||||
| F:	kernel/srcu* | ||||
| 
 | ||||
| SMACK SECURITY MODULE | ||||
| M:	Casey Schaufler <casey@schaufler-ca.com> | ||||
| L:	linux-security-module@vger.kernel.org | ||||
| W:	http://schaufler-ca.com | ||||
| T:	git git://git.gitorious.org/smack-next/kernel.git | ||||
| S:	Maintained | ||||
| F:	Documentation/security/Smack.txt | ||||
| F:	security/smack/ | ||||
| 
 | ||||
| SMC91x ETHERNET DRIVER | ||||
| M:	Nicolas Pitre <nico@fluxnic.net> | ||||
| S:	Odd Fixes | ||||
| @ -6862,10 +6871,11 @@ F:	include/linux/shmem_fs.h | ||||
| F:	mm/shmem.c | ||||
| 
 | ||||
| TPM DEVICE DRIVER | ||||
| M:	Debora Velarde <debora@linux.vnet.ibm.com> | ||||
| M:	Rajiv Andrade <srajiv@linux.vnet.ibm.com> | ||||
| M:	Kent Yoder <key@linux.vnet.ibm.com> | ||||
| M:	Rajiv Andrade <mail@srajiv.net> | ||||
| W:	http://tpmdd.sourceforge.net | ||||
| M:	Marcel Selhorst <m.selhorst@sirrix.com> | ||||
| M:	Marcel Selhorst <tpmdd@selhorst.net> | ||||
| M:	Sirrix AG <tpmdd@sirrix.com> | ||||
| W:	http://www.sirrix.com | ||||
| L:	tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers) | ||||
| S:	Maintained | ||||
|  | ||||
| @ -827,10 +827,10 @@ EXPORT_SYMBOL_GPL(tpm_pcr_extend); | ||||
| int tpm_do_selftest(struct tpm_chip *chip) | ||||
| { | ||||
| 	int rc; | ||||
| 	u8 digest[TPM_DIGEST_SIZE]; | ||||
| 	unsigned int loops; | ||||
| 	unsigned int delay_msec = 1000; | ||||
| 	unsigned long duration; | ||||
| 	struct tpm_cmd_t cmd; | ||||
| 
 | ||||
| 	duration = tpm_calc_ordinal_duration(chip, | ||||
| 	                                     TPM_ORD_CONTINUE_SELFTEST); | ||||
| @ -845,7 +845,15 @@ int tpm_do_selftest(struct tpm_chip *chip) | ||||
| 		return rc; | ||||
| 
 | ||||
| 	do { | ||||
| 		rc = __tpm_pcr_read(chip, 0, digest); | ||||
| 		/* Attempt to read a PCR value */ | ||||
| 		cmd.header.in = pcrread_header; | ||||
| 		cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); | ||||
| 		rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); | ||||
| 
 | ||||
| 		if (rc < TPM_HEADER_SIZE) | ||||
| 			return -EFAULT; | ||||
| 
 | ||||
| 		rc = be32_to_cpu(cmd.header.out.return_code); | ||||
| 		if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { | ||||
| 			dev_info(chip->dev, | ||||
| 				 "TPM is disabled/deactivated (0x%X)\n", rc); | ||||
| @ -1322,6 +1330,9 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); | ||||
| 
 | ||||
| void tpm_dev_vendor_release(struct tpm_chip *chip) | ||||
| { | ||||
| 	if (!chip) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (chip->vendor.release) | ||||
| 		chip->vendor.release(chip->dev); | ||||
| 
 | ||||
| @ -1339,6 +1350,9 @@ void tpm_dev_release(struct device *dev) | ||||
| { | ||||
| 	struct tpm_chip *chip = dev_get_drvdata(dev); | ||||
| 
 | ||||
| 	if (!chip) | ||||
| 		return; | ||||
| 
 | ||||
| 	tpm_dev_vendor_release(chip); | ||||
| 
 | ||||
| 	chip->release(dev); | ||||
| @ -1405,15 +1419,12 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, | ||||
| 			"unable to misc_register %s, minor %d\n", | ||||
| 			chip->vendor.miscdev.name, | ||||
| 			chip->vendor.miscdev.minor); | ||||
| 		put_device(chip->dev); | ||||
| 		return NULL; | ||||
| 		goto put_device; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { | ||||
| 		misc_deregister(&chip->vendor.miscdev); | ||||
| 		put_device(chip->dev); | ||||
| 
 | ||||
| 		return NULL; | ||||
| 		goto put_device; | ||||
| 	} | ||||
| 
 | ||||
| 	chip->bios_dir = tpm_bios_log_setup(devname); | ||||
| @ -1425,6 +1436,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, | ||||
| 
 | ||||
| 	return chip; | ||||
| 
 | ||||
| put_device: | ||||
| 	put_device(chip->dev); | ||||
| out_free: | ||||
| 	kfree(chip); | ||||
| 	kfree(devname); | ||||
|  | ||||
| @ -4,8 +4,8 @@ | ||||
|  * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module | ||||
|  * Specifications at www.trustedcomputinggroup.org | ||||
|  * | ||||
|  * Copyright (C) 2005, Marcel Selhorst <m.selhorst@sirrix.com> | ||||
|  * Sirrix AG - security technologies, http://www.sirrix.com and
 | ||||
|  * Copyright (C) 2005, Marcel Selhorst <tpmdd@selhorst.net> | ||||
|  * Sirrix AG - security technologies <tpmdd@sirrix.com> and | ||||
|  * Applied Data Security Group, Ruhr-University Bochum, Germany | ||||
|  * Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ 
 | ||||
|  * | ||||
| @ -671,7 +671,7 @@ static void __exit cleanup_inf(void) | ||||
| module_init(init_inf); | ||||
| module_exit(cleanup_inf); | ||||
| 
 | ||||
| MODULE_AUTHOR("Marcel Selhorst <m.selhorst@sirrix.com>"); | ||||
| MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>"); | ||||
| MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); | ||||
| MODULE_VERSION("1.9.2"); | ||||
| MODULE_LICENSE("GPL"); | ||||
|  | ||||
| @ -378,14 +378,6 @@ config MPILIB | ||||
| 	  It is used to implement RSA digital signature verification, | ||||
| 	  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 | ||||
| 	tristate | ||||
| 	depends on KEYS && CRYPTO | ||||
|  | ||||
| @ -19,14 +19,3 @@ mpi-y = \ | ||||
| 	mpih-mul.o			\
 | ||||
| 	mpi-pow.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; | ||||
| } | ||||
| @ -54,165 +54,3 @@ unsigned mpi_get_nbits(MPI a) | ||||
| 	return n; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(mpi_get_nbits); | ||||
| 
 | ||||
| /****************
 | ||||
|  * Test whether bit N is set. | ||||
|  */ | ||||
| int mpi_test_bit(MPI a, unsigned n) | ||||
| { | ||||
| 	unsigned limbno, bitno; | ||||
| 	mpi_limb_t limb; | ||||
| 
 | ||||
| 	limbno = n / BITS_PER_MPI_LIMB; | ||||
| 	bitno = n % BITS_PER_MPI_LIMB; | ||||
| 
 | ||||
| 	if (limbno >= a->nlimbs) | ||||
| 		return 0;	/* too far left: this is a 0 */ | ||||
| 	limb = a->d[limbno]; | ||||
| 	return (limb & (A_LIMB_1 << bitno)) ? 1 : 0; | ||||
| } | ||||
| 
 | ||||
| /****************
 | ||||
|  * Set bit N of A. | ||||
|  */ | ||||
| int mpi_set_bit(MPI a, unsigned n) | ||||
| { | ||||
| 	unsigned limbno, bitno; | ||||
| 
 | ||||
| 	limbno = n / BITS_PER_MPI_LIMB; | ||||
| 	bitno = n % BITS_PER_MPI_LIMB; | ||||
| 
 | ||||
| 	if (limbno >= a->nlimbs) {	/* resize */ | ||||
| 		if (a->alloced >= limbno) | ||||
| 			if (mpi_resize(a, limbno + 1) < 0) | ||||
| 				return -ENOMEM; | ||||
| 		a->nlimbs = limbno + 1; | ||||
| 	} | ||||
| 	a->d[limbno] |= (A_LIMB_1 << bitno); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /****************
 | ||||
|  * Set bit N of A. and clear all bits above | ||||
|  */ | ||||
| int mpi_set_highbit(MPI a, unsigned n) | ||||
| { | ||||
| 	unsigned limbno, bitno; | ||||
| 
 | ||||
| 	limbno = n / BITS_PER_MPI_LIMB; | ||||
| 	bitno = n % BITS_PER_MPI_LIMB; | ||||
| 
 | ||||
| 	if (limbno >= a->nlimbs) {	/* resize */ | ||||
| 		if (a->alloced >= limbno) | ||||
| 			if (mpi_resize(a, limbno + 1) < 0) | ||||
| 				return -ENOMEM; | ||||
| 		a->nlimbs = limbno + 1; | ||||
| 	} | ||||
| 	a->d[limbno] |= (A_LIMB_1 << bitno); | ||||
| 	for (bitno++; bitno < BITS_PER_MPI_LIMB; bitno++) | ||||
| 		a->d[limbno] &= ~(A_LIMB_1 << bitno); | ||||
| 	a->nlimbs = limbno + 1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /****************
 | ||||
|  * clear bit N of A and all bits above | ||||
|  */ | ||||
| void mpi_clear_highbit(MPI a, unsigned n) | ||||
| { | ||||
| 	unsigned limbno, bitno; | ||||
| 
 | ||||
| 	limbno = n / BITS_PER_MPI_LIMB; | ||||
| 	bitno = n % BITS_PER_MPI_LIMB; | ||||
| 
 | ||||
| 	if (limbno >= a->nlimbs) | ||||
| 		return;		/* not allocated, so need to clear bits :-) */ | ||||
| 
 | ||||
| 	for (; bitno < BITS_PER_MPI_LIMB; bitno++) | ||||
| 		a->d[limbno] &= ~(A_LIMB_1 << bitno); | ||||
| 	a->nlimbs = limbno + 1; | ||||
| } | ||||
| 
 | ||||
| /****************
 | ||||
|  * Clear bit N of A. | ||||
|  */ | ||||
| void mpi_clear_bit(MPI a, unsigned n) | ||||
| { | ||||
| 	unsigned limbno, bitno; | ||||
| 
 | ||||
| 	limbno = n / BITS_PER_MPI_LIMB; | ||||
| 	bitno = n % BITS_PER_MPI_LIMB; | ||||
| 
 | ||||
| 	if (limbno >= a->nlimbs) | ||||
| 		return;		/* don't need to clear this bit, it's to far to left */ | ||||
| 	a->d[limbno] &= ~(A_LIMB_1 << bitno); | ||||
| } | ||||
| 
 | ||||
| /****************
 | ||||
|  * Shift A by N bits to the right | ||||
|  * FIXME: should use alloc_limb if X and A are same. | ||||
|  */ | ||||
| int mpi_rshift(MPI x, MPI a, unsigned n) | ||||
| { | ||||
| 	mpi_ptr_t xp; | ||||
| 	mpi_size_t xsize; | ||||
| 
 | ||||
| 	xsize = a->nlimbs; | ||||
| 	x->sign = a->sign; | ||||
| 	if (RESIZE_IF_NEEDED(x, (size_t) xsize) < 0) | ||||
| 		return -ENOMEM; | ||||
| 	xp = x->d; | ||||
| 
 | ||||
| 	if (xsize) { | ||||
| 		mpihelp_rshift(xp, a->d, xsize, n); | ||||
| 		MPN_NORMALIZE(xp, xsize); | ||||
| 	} | ||||
| 	x->nlimbs = xsize; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /****************
 | ||||
|  * Shift A by COUNT limbs to the left | ||||
|  * This is used only within the MPI library | ||||
|  */ | ||||
| int mpi_lshift_limbs(MPI a, unsigned int count) | ||||
| { | ||||
| 	const int n = a->nlimbs; | ||||
| 	mpi_ptr_t ap; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!count || !n) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (RESIZE_IF_NEEDED(a, n + count) < 0) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	ap = a->d; | ||||
| 	for (i = n - 1; i >= 0; i--) | ||||
| 		ap[i + count] = ap[i]; | ||||
| 	for (i = 0; i < count; i++) | ||||
| 		ap[i] = 0; | ||||
| 	a->nlimbs += count; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /****************
 | ||||
|  * Shift A by COUNT limbs to the right | ||||
|  * This is used only within the MPI library | ||||
|  */ | ||||
| void mpi_rshift_limbs(MPI a, unsigned int count) | ||||
| { | ||||
| 	mpi_ptr_t ap = a->d; | ||||
| 	mpi_size_t n = a->nlimbs; | ||||
| 	unsigned int i; | ||||
| 
 | ||||
| 	if (count >= n) { | ||||
| 		a->nlimbs = 0; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < n - count; i++) | ||||
| 		ap[i] = ap[i + count]; | ||||
| 	ap[i] = 0; | ||||
| 	a->nlimbs -= count; | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
| } | ||||
| @ -73,81 +73,6 @@ leave: | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(mpi_read_from_buffer); | ||||
| 
 | ||||
| /****************
 | ||||
|  * Make an mpi from a character string. | ||||
|  */ | ||||
| int mpi_fromstr(MPI val, const char *str) | ||||
| { | ||||
| 	int hexmode = 0, sign = 0, prepend_zero = 0, i, j, c, c1, c2; | ||||
| 	unsigned nbits, nbytes, nlimbs; | ||||
| 	mpi_limb_t a; | ||||
| 
 | ||||
| 	if (*str == '-') { | ||||
| 		sign = 1; | ||||
| 		str++; | ||||
| 	} | ||||
| 	if (*str == '0' && str[1] == 'x') | ||||
| 		hexmode = 1; | ||||
| 	else | ||||
| 		return -EINVAL;	/* other bases are not yet supported */ | ||||
| 	str += 2; | ||||
| 
 | ||||
| 	nbits = strlen(str) * 4; | ||||
| 	if (nbits % 8) | ||||
| 		prepend_zero = 1; | ||||
| 	nbytes = (nbits + 7) / 8; | ||||
| 	nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; | ||||
| 	if (val->alloced < nlimbs) | ||||
| 		if (!mpi_resize(val, nlimbs)) | ||||
| 			return -ENOMEM; | ||||
| 	i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | ||||
| 	i %= BYTES_PER_MPI_LIMB; | ||||
| 	j = val->nlimbs = nlimbs; | ||||
| 	val->sign = sign; | ||||
| 	for (; j > 0; j--) { | ||||
| 		a = 0; | ||||
| 		for (; i < BYTES_PER_MPI_LIMB; i++) { | ||||
| 			if (prepend_zero) { | ||||
| 				c1 = '0'; | ||||
| 				prepend_zero = 0; | ||||
| 			} else | ||||
| 				c1 = *str++; | ||||
| 			assert(c1); | ||||
| 			c2 = *str++; | ||||
| 			assert(c2); | ||||
| 			if (c1 >= '0' && c1 <= '9') | ||||
| 				c = c1 - '0'; | ||||
| 			else if (c1 >= 'a' && c1 <= 'f') | ||||
| 				c = c1 - 'a' + 10; | ||||
| 			else if (c1 >= 'A' && c1 <= 'F') | ||||
| 				c = c1 - 'A' + 10; | ||||
| 			else { | ||||
| 				mpi_clear(val); | ||||
| 				return 1; | ||||
| 			} | ||||
| 			c <<= 4; | ||||
| 			if (c2 >= '0' && c2 <= '9') | ||||
| 				c |= c2 - '0'; | ||||
| 			else if (c2 >= 'a' && c2 <= 'f') | ||||
| 				c |= c2 - 'a' + 10; | ||||
| 			else if (c2 >= 'A' && c2 <= 'F') | ||||
| 				c |= c2 - 'A' + 10; | ||||
| 			else { | ||||
| 				mpi_clear(val); | ||||
| 				return 1; | ||||
| 			} | ||||
| 			a <<= 8; | ||||
| 			a |= c; | ||||
| 		} | ||||
| 		i = 0; | ||||
| 
 | ||||
| 		val->d[j - 1] = a; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(mpi_fromstr); | ||||
| 
 | ||||
| /****************
 | ||||
|  * Return an allocated buffer with the MPI (msb first). | ||||
|  * NBYTES receives the length of this buffer. Caller must free the | ||||
|  | ||||
| @ -37,159 +37,6 @@ | ||||
| #define UDIV_TIME UMUL_TIME | ||||
| #endif | ||||
| 
 | ||||
| /* FIXME: We should be using invert_limb (or invert_normalized_limb)
 | ||||
|  * here (not udiv_qrnnd). | ||||
|  */ | ||||
| 
 | ||||
| mpi_limb_t | ||||
| mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, | ||||
| 	      mpi_limb_t divisor_limb) | ||||
| { | ||||
| 	mpi_size_t i; | ||||
| 	mpi_limb_t n1, n0, r; | ||||
| 	int dummy; | ||||
| 
 | ||||
| 	/* Botch: Should this be handled at all?  Rely on callers?  */ | ||||
| 	if (!dividend_size) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* If multiplication is much faster than division, and the
 | ||||
| 	 * dividend is large, pre-invert the divisor, and use | ||||
| 	 * only multiplications in the inner loop. | ||||
| 	 * | ||||
| 	 * This test should be read: | ||||
| 	 *   Does it ever help to use udiv_qrnnd_preinv? | ||||
| 	 *     && Does what we save compensate for the inversion overhead? | ||||
| 	 */ | ||||
| 	if (UDIV_TIME > (2 * UMUL_TIME + 6) | ||||
| 	    && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) { | ||||
| 		int normalization_steps; | ||||
| 
 | ||||
| 		count_leading_zeros(normalization_steps, divisor_limb); | ||||
| 		if (normalization_steps) { | ||||
| 			mpi_limb_t divisor_limb_inverted; | ||||
| 
 | ||||
| 			divisor_limb <<= normalization_steps; | ||||
| 
 | ||||
| 			/* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
 | ||||
| 			 * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the | ||||
| 			 * most significant bit (with weight 2**N) implicit. | ||||
| 			 * | ||||
| 			 * Special case for DIVISOR_LIMB == 100...000. | ||||
| 			 */ | ||||
| 			if (!(divisor_limb << 1)) | ||||
| 				divisor_limb_inverted = ~(mpi_limb_t) 0; | ||||
| 			else | ||||
| 				udiv_qrnnd(divisor_limb_inverted, dummy, | ||||
| 					   -divisor_limb, 0, divisor_limb); | ||||
| 
 | ||||
| 			n1 = dividend_ptr[dividend_size - 1]; | ||||
| 			r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); | ||||
| 
 | ||||
| 			/* Possible optimization:
 | ||||
| 			 * if (r == 0 | ||||
| 			 * && divisor_limb > ((n1 << normalization_steps) | ||||
| 			 *                 | (dividend_ptr[dividend_size - 2] >> ...))) | ||||
| 			 * ...one division less... | ||||
| 			 */ | ||||
| 			for (i = dividend_size - 2; i >= 0; i--) { | ||||
| 				n0 = dividend_ptr[i]; | ||||
| 				UDIV_QRNND_PREINV(dummy, r, r, | ||||
| 						  ((n1 << normalization_steps) | ||||
| 						   | (n0 >> | ||||
| 						      (BITS_PER_MPI_LIMB - | ||||
| 						       normalization_steps))), | ||||
| 						  divisor_limb, | ||||
| 						  divisor_limb_inverted); | ||||
| 				n1 = n0; | ||||
| 			} | ||||
| 			UDIV_QRNND_PREINV(dummy, r, r, | ||||
| 					  n1 << normalization_steps, | ||||
| 					  divisor_limb, divisor_limb_inverted); | ||||
| 			return r >> normalization_steps; | ||||
| 		} else { | ||||
| 			mpi_limb_t divisor_limb_inverted; | ||||
| 
 | ||||
| 			/* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
 | ||||
| 			 * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the | ||||
| 			 * most significant bit (with weight 2**N) implicit. | ||||
| 			 * | ||||
| 			 * Special case for DIVISOR_LIMB == 100...000. | ||||
| 			 */ | ||||
| 			if (!(divisor_limb << 1)) | ||||
| 				divisor_limb_inverted = ~(mpi_limb_t) 0; | ||||
| 			else | ||||
| 				udiv_qrnnd(divisor_limb_inverted, dummy, | ||||
| 					   -divisor_limb, 0, divisor_limb); | ||||
| 
 | ||||
| 			i = dividend_size - 1; | ||||
| 			r = dividend_ptr[i]; | ||||
| 
 | ||||
| 			if (r >= divisor_limb) | ||||
| 				r = 0; | ||||
| 			else | ||||
| 				i--; | ||||
| 
 | ||||
| 			for (; i >= 0; i--) { | ||||
| 				n0 = dividend_ptr[i]; | ||||
| 				UDIV_QRNND_PREINV(dummy, r, r, | ||||
| 						  n0, divisor_limb, | ||||
| 						  divisor_limb_inverted); | ||||
| 			} | ||||
| 			return r; | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (UDIV_NEEDS_NORMALIZATION) { | ||||
| 			int normalization_steps; | ||||
| 
 | ||||
| 			count_leading_zeros(normalization_steps, divisor_limb); | ||||
| 			if (normalization_steps) { | ||||
| 				divisor_limb <<= normalization_steps; | ||||
| 
 | ||||
| 				n1 = dividend_ptr[dividend_size - 1]; | ||||
| 				r = n1 >> (BITS_PER_MPI_LIMB - | ||||
| 					   normalization_steps); | ||||
| 
 | ||||
| 				/* Possible optimization:
 | ||||
| 				 * if (r == 0 | ||||
| 				 * && divisor_limb > ((n1 << normalization_steps) | ||||
| 				 *                 | (dividend_ptr[dividend_size - 2] >> ...))) | ||||
| 				 * ...one division less... | ||||
| 				 */ | ||||
| 				for (i = dividend_size - 2; i >= 0; i--) { | ||||
| 					n0 = dividend_ptr[i]; | ||||
| 					udiv_qrnnd(dummy, r, r, | ||||
| 						   ((n1 << normalization_steps) | ||||
| 						    | (n0 >> | ||||
| 						       (BITS_PER_MPI_LIMB - | ||||
| 							normalization_steps))), | ||||
| 						   divisor_limb); | ||||
| 					n1 = n0; | ||||
| 				} | ||||
| 				udiv_qrnnd(dummy, r, r, | ||||
| 					   n1 << normalization_steps, | ||||
| 					   divisor_limb); | ||||
| 				return r >> normalization_steps; | ||||
| 			} | ||||
| 		} | ||||
| 		/* No normalization needed, either because udiv_qrnnd doesn't require
 | ||||
| 		 * it, or because DIVISOR_LIMB is already normalized.  */ | ||||
| 		i = dividend_size - 1; | ||||
| 		r = dividend_ptr[i]; | ||||
| 
 | ||||
| 		if (r >= divisor_limb) | ||||
| 			r = 0; | ||||
| 		else | ||||
| 			i--; | ||||
| 
 | ||||
| 		for (; i >= 0; i--) { | ||||
| 			n0 = dividend_ptr[i]; | ||||
| 			udiv_qrnnd(dummy, r, r, n0, divisor_limb); | ||||
| 		} | ||||
| 		return r; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Divide num (NP/NSIZE) by den (DP/DSIZE) and write
 | ||||
|  * the NSIZE-DSIZE least significant quotient limbs at QP | ||||
|  * and the DSIZE long remainder at NP.	If QEXTRA_LIMBS is | ||||
| @ -387,159 +234,3 @@ q_test: | ||||
| 
 | ||||
| 	return most_significant_q_limb; | ||||
| } | ||||
| 
 | ||||
| /****************
 | ||||
|  * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. | ||||
|  * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. | ||||
|  * Return the single-limb remainder. | ||||
|  * There are no constraints on the value of the divisor. | ||||
|  * | ||||
|  * QUOT_PTR and DIVIDEND_PTR might point to the same limb. | ||||
|  */ | ||||
| 
 | ||||
| mpi_limb_t | ||||
| mpihelp_divmod_1(mpi_ptr_t quot_ptr, | ||||
| 		 mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, | ||||
| 		 mpi_limb_t divisor_limb) | ||||
| { | ||||
| 	mpi_size_t i; | ||||
| 	mpi_limb_t n1, n0, r; | ||||
| 	int dummy; | ||||
| 
 | ||||
| 	if (!dividend_size) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* If multiplication is much faster than division, and the
 | ||||
| 	 * dividend is large, pre-invert the divisor, and use | ||||
| 	 * only multiplications in the inner loop. | ||||
| 	 * | ||||
| 	 * This test should be read: | ||||
| 	 * Does it ever help to use udiv_qrnnd_preinv? | ||||
| 	 * && Does what we save compensate for the inversion overhead? | ||||
| 	 */ | ||||
| 	if (UDIV_TIME > (2 * UMUL_TIME + 6) | ||||
| 	    && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) { | ||||
| 		int normalization_steps; | ||||
| 
 | ||||
| 		count_leading_zeros(normalization_steps, divisor_limb); | ||||
| 		if (normalization_steps) { | ||||
| 			mpi_limb_t divisor_limb_inverted; | ||||
| 
 | ||||
| 			divisor_limb <<= normalization_steps; | ||||
| 
 | ||||
| 			/* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
 | ||||
| 			 * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the | ||||
| 			 * most significant bit (with weight 2**N) implicit. | ||||
| 			 */ | ||||
| 			/* Special case for DIVISOR_LIMB == 100...000.  */ | ||||
| 			if (!(divisor_limb << 1)) | ||||
| 				divisor_limb_inverted = ~(mpi_limb_t) 0; | ||||
| 			else | ||||
| 				udiv_qrnnd(divisor_limb_inverted, dummy, | ||||
| 					   -divisor_limb, 0, divisor_limb); | ||||
| 
 | ||||
| 			n1 = dividend_ptr[dividend_size - 1]; | ||||
| 			r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); | ||||
| 
 | ||||
| 			/* Possible optimization:
 | ||||
| 			 * if (r == 0 | ||||
| 			 * && divisor_limb > ((n1 << normalization_steps) | ||||
| 			 *                 | (dividend_ptr[dividend_size - 2] >> ...))) | ||||
| 			 * ...one division less... | ||||
| 			 */ | ||||
| 			for (i = dividend_size - 2; i >= 0; i--) { | ||||
| 				n0 = dividend_ptr[i]; | ||||
| 				UDIV_QRNND_PREINV(quot_ptr[i + 1], r, r, | ||||
| 						  ((n1 << normalization_steps) | ||||
| 						   | (n0 >> | ||||
| 						      (BITS_PER_MPI_LIMB - | ||||
| 						       normalization_steps))), | ||||
| 						  divisor_limb, | ||||
| 						  divisor_limb_inverted); | ||||
| 				n1 = n0; | ||||
| 			} | ||||
| 			UDIV_QRNND_PREINV(quot_ptr[0], r, r, | ||||
| 					  n1 << normalization_steps, | ||||
| 					  divisor_limb, divisor_limb_inverted); | ||||
| 			return r >> normalization_steps; | ||||
| 		} else { | ||||
| 			mpi_limb_t divisor_limb_inverted; | ||||
| 
 | ||||
| 			/* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
 | ||||
| 			 * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the | ||||
| 			 * most significant bit (with weight 2**N) implicit. | ||||
| 			 */ | ||||
| 			/* Special case for DIVISOR_LIMB == 100...000.  */ | ||||
| 			if (!(divisor_limb << 1)) | ||||
| 				divisor_limb_inverted = ~(mpi_limb_t) 0; | ||||
| 			else | ||||
| 				udiv_qrnnd(divisor_limb_inverted, dummy, | ||||
| 					   -divisor_limb, 0, divisor_limb); | ||||
| 
 | ||||
| 			i = dividend_size - 1; | ||||
| 			r = dividend_ptr[i]; | ||||
| 
 | ||||
| 			if (r >= divisor_limb) | ||||
| 				r = 0; | ||||
| 			else | ||||
| 				quot_ptr[i--] = 0; | ||||
| 
 | ||||
| 			for (; i >= 0; i--) { | ||||
| 				n0 = dividend_ptr[i]; | ||||
| 				UDIV_QRNND_PREINV(quot_ptr[i], r, r, | ||||
| 						  n0, divisor_limb, | ||||
| 						  divisor_limb_inverted); | ||||
| 			} | ||||
| 			return r; | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (UDIV_NEEDS_NORMALIZATION) { | ||||
| 			int normalization_steps; | ||||
| 
 | ||||
| 			count_leading_zeros(normalization_steps, divisor_limb); | ||||
| 			if (normalization_steps) { | ||||
| 				divisor_limb <<= normalization_steps; | ||||
| 
 | ||||
| 				n1 = dividend_ptr[dividend_size - 1]; | ||||
| 				r = n1 >> (BITS_PER_MPI_LIMB - | ||||
| 					   normalization_steps); | ||||
| 
 | ||||
| 				/* Possible optimization:
 | ||||
| 				 * if (r == 0 | ||||
| 				 * && divisor_limb > ((n1 << normalization_steps) | ||||
| 				 *                 | (dividend_ptr[dividend_size - 2] >> ...))) | ||||
| 				 * ...one division less... | ||||
| 				 */ | ||||
| 				for (i = dividend_size - 2; i >= 0; i--) { | ||||
| 					n0 = dividend_ptr[i]; | ||||
| 					udiv_qrnnd(quot_ptr[i + 1], r, r, | ||||
| 						   ((n1 << normalization_steps) | ||||
| 						    | (n0 >> | ||||
| 						       (BITS_PER_MPI_LIMB - | ||||
| 							normalization_steps))), | ||||
| 						   divisor_limb); | ||||
| 					n1 = n0; | ||||
| 				} | ||||
| 				udiv_qrnnd(quot_ptr[0], r, r, | ||||
| 					   n1 << normalization_steps, | ||||
| 					   divisor_limb); | ||||
| 				return r >> normalization_steps; | ||||
| 			} | ||||
| 		} | ||||
| 		/* No normalization needed, either because udiv_qrnnd doesn't require
 | ||||
| 		 * it, or because DIVISOR_LIMB is already normalized.  */ | ||||
| 		i = dividend_size - 1; | ||||
| 		r = dividend_ptr[i]; | ||||
| 
 | ||||
| 		if (r >= divisor_limb) | ||||
| 			r = 0; | ||||
| 		else | ||||
| 			quot_ptr[i--] = 0; | ||||
| 
 | ||||
| 		for (; i >= 0; i--) { | ||||
| 			n0 = dividend_ptr[i]; | ||||
| 			udiv_qrnnd(quot_ptr[i], r, r, n0, divisor_limb); | ||||
| 		} | ||||
| 		return r; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -330,36 +330,6 @@ mpih_sqr_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* This should be made into an inline function in gmp.h.  */ | ||||
| int mpihelp_mul_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) | ||||
| { | ||||
| 	if (up == vp) { | ||||
| 		if (size < KARATSUBA_THRESHOLD) | ||||
| 			mpih_sqr_n_basecase(prodp, up, size); | ||||
| 		else { | ||||
| 			mpi_ptr_t tspace; | ||||
| 			tspace = mpi_alloc_limb_space(2 * size); | ||||
| 			if (!tspace) | ||||
| 				return -ENOMEM; | ||||
| 			mpih_sqr_n(prodp, up, size, tspace); | ||||
| 			mpi_free_limb_space(tspace); | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (size < KARATSUBA_THRESHOLD) | ||||
| 			mul_n_basecase(prodp, up, vp, size); | ||||
| 		else { | ||||
| 			mpi_ptr_t tspace; | ||||
| 			tspace = mpi_alloc_limb_space(2 * size); | ||||
| 			if (!tspace) | ||||
| 				return -ENOMEM; | ||||
| 			mul_n(prodp, up, vp, size, tspace); | ||||
| 			mpi_free_limb_space(tspace); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| mpihelp_mul_karatsuba_case(mpi_ptr_t prodp, | ||||
| 			   mpi_ptr_t up, mpi_size_t usize, | ||||
|  | ||||
| @ -106,13 +106,6 @@ int mpi_resize(MPI a, unsigned nlimbs) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void mpi_clear(MPI a) | ||||
| { | ||||
| 	a->nlimbs = 0; | ||||
| 	a->nbits = 0; | ||||
| 	a->flags = 0; | ||||
| } | ||||
| 
 | ||||
| void mpi_free(MPI a) | ||||
| { | ||||
| 	if (!a) | ||||
| @ -128,84 +121,3 @@ void mpi_free(MPI a) | ||||
| 	kfree(a); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(mpi_free); | ||||
| 
 | ||||
| /****************
 | ||||
|  * Note: This copy function should not interpret the MPI | ||||
|  *	 but copy it transparently. | ||||
|  */ | ||||
| int mpi_copy(MPI *copied, const MPI a) | ||||
| { | ||||
| 	size_t i; | ||||
| 	MPI b; | ||||
| 
 | ||||
| 	*copied = NULL; | ||||
| 
 | ||||
| 	if (a) { | ||||
| 		b = mpi_alloc(a->nlimbs); | ||||
| 		if (!b) | ||||
| 			return -ENOMEM; | ||||
| 
 | ||||
| 		b->nlimbs = a->nlimbs; | ||||
| 		b->sign = a->sign; | ||||
| 		b->flags = a->flags; | ||||
| 		b->nbits = a->nbits; | ||||
| 
 | ||||
| 		for (i = 0; i < b->nlimbs; i++) | ||||
| 			b->d[i] = a->d[i]; | ||||
| 
 | ||||
| 		*copied = b; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int mpi_set(MPI w, const MPI u) | ||||
| { | ||||
| 	mpi_ptr_t wp, up; | ||||
| 	mpi_size_t usize = u->nlimbs; | ||||
| 	int usign = u->sign; | ||||
| 
 | ||||
| 	if (RESIZE_IF_NEEDED(w, (size_t) usize) < 0) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	wp = w->d; | ||||
| 	up = u->d; | ||||
| 	MPN_COPY(wp, up, usize); | ||||
| 	w->nlimbs = usize; | ||||
| 	w->nbits = u->nbits; | ||||
| 	w->flags = u->flags; | ||||
| 	w->sign = usign; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int mpi_set_ui(MPI w, unsigned long u) | ||||
| { | ||||
| 	if (RESIZE_IF_NEEDED(w, 1) < 0) | ||||
| 		return -ENOMEM; | ||||
| 	w->d[0] = u; | ||||
| 	w->nlimbs = u ? 1 : 0; | ||||
| 	w->sign = 0; | ||||
| 	w->nbits = 0; | ||||
| 	w->flags = 0; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| MPI mpi_alloc_set_ui(unsigned long u) | ||||
| { | ||||
| 	MPI w = mpi_alloc(1); | ||||
| 	if (!w) | ||||
| 		return w; | ||||
| 	w->d[0] = u; | ||||
| 	w->nlimbs = u ? 1 : 0; | ||||
| 	w->sign = 0; | ||||
| 	return w; | ||||
| } | ||||
| 
 | ||||
| void mpi_swap(MPI a, MPI b) | ||||
| { | ||||
| 	struct gcry_mpi tmp; | ||||
| 
 | ||||
| 	tmp = *a; | ||||
| 	*a = *b; | ||||
| 	*b = tmp; | ||||
| } | ||||
|  | ||||
							
								
								
									
										3
									
								
								samples/seccomp/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								samples/seccomp/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| bpf-direct | ||||
| bpf-fancy | ||||
| dropper | ||||
| @ -38,8 +38,9 @@ config IMA_MEASURE_PCR_IDX | ||||
| 	  measurement list.  If unsure, use the default 10. | ||||
| 
 | ||||
| config IMA_AUDIT | ||||
| 	bool | ||||
| 	bool "Enables auditing support" | ||||
| 	depends on IMA | ||||
| 	depends on AUDIT | ||||
| 	default y | ||||
| 	help | ||||
| 	  This option adds a kernel parameter 'ima_audit', which | ||||
|  | ||||
| @ -6,4 +6,5 @@ | ||||
| obj-$(CONFIG_IMA) += ima.o | ||||
| 
 | ||||
| ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
 | ||||
| 	 ima_policy.o ima_audit.o | ||||
| 	 ima_policy.o | ||||
| ima-$(CONFIG_IMA_AUDIT) += ima_audit.o | ||||
|  | ||||
| @ -61,10 +61,19 @@ struct ima_queue_entry { | ||||
| }; | ||||
| extern struct list_head ima_measurements;	/* list of all measurements */ | ||||
| 
 | ||||
| #ifdef CONFIG_IMA_AUDIT | ||||
| /* declarations */ | ||||
| void integrity_audit_msg(int audit_msgno, struct inode *inode, | ||||
| 			 const unsigned char *fname, const char *op, | ||||
| 			 const char *cause, int result, int info); | ||||
| #else | ||||
| static inline void integrity_audit_msg(int audit_msgno, struct inode *inode, | ||||
| 				       const unsigned char *fname, | ||||
| 				       const char *op, const char *cause, | ||||
| 				       int result, int info) | ||||
| { | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* Internal IMA function definitions */ | ||||
| int ima_init(void); | ||||
|  | ||||
| @ -175,7 +175,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint, | ||||
| 	} | ||||
| 	memset(&entry->template, 0, sizeof(entry->template)); | ||||
| 	memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE); | ||||
| 	strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX); | ||||
| 	strcpy(entry->template.file_name, | ||||
| 	       (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ? | ||||
| 	       file->f_dentry->d_name.name : filename); | ||||
| 
 | ||||
| 	result = ima_store_template(entry, violation, inode); | ||||
| 	if (!result || result == -EEXIST) | ||||
|  | ||||
| @ -17,8 +17,6 @@ | ||||
| 
 | ||||
| static int ima_audit; | ||||
| 
 | ||||
| #ifdef CONFIG_IMA_AUDIT | ||||
| 
 | ||||
| /* ima_audit_setup - enable informational auditing messages */ | ||||
| static int __init ima_audit_setup(char *str) | ||||
| { | ||||
| @ -29,7 +27,6 @@ static int __init ima_audit_setup(char *str) | ||||
| 	return 1; | ||||
| } | ||||
| __setup("ima_audit=", ima_audit_setup); | ||||
| #endif | ||||
| 
 | ||||
| void integrity_audit_msg(int audit_msgno, struct inode *inode, | ||||
| 			 const unsigned char *fname, const char *op, | ||||
|  | ||||
| @ -367,6 +367,7 @@ int __init ima_fs_init(void) | ||||
| 
 | ||||
| 	return 0; | ||||
| out: | ||||
| 	securityfs_remove(violations); | ||||
| 	securityfs_remove(runtime_measurements_count); | ||||
| 	securityfs_remove(ascii_runtime_measurements); | ||||
| 	securityfs_remove(binary_runtime_measurements); | ||||
| @ -374,13 +375,3 @@ out: | ||||
| 	securityfs_remove(ima_policy); | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| void __exit ima_fs_cleanup(void) | ||||
| { | ||||
| 	securityfs_remove(violations); | ||||
| 	securityfs_remove(runtime_measurements_count); | ||||
| 	securityfs_remove(ascii_runtime_measurements); | ||||
| 	securityfs_remove(binary_runtime_measurements); | ||||
| 	securityfs_remove(ima_dir); | ||||
| 	securityfs_remove(ima_policy); | ||||
| } | ||||
|  | ||||
| @ -90,8 +90,3 @@ int __init ima_init(void) | ||||
| 
 | ||||
| 	return ima_fs_init(); | ||||
| } | ||||
| 
 | ||||
| void __exit ima_cleanup(void) | ||||
| { | ||||
| 	ima_fs_cleanup(); | ||||
| } | ||||
|  | ||||
| @ -54,6 +54,7 @@ static void ima_rdwr_violation_check(struct file *file) | ||||
| 	fmode_t mode = file->f_mode; | ||||
| 	int rc; | ||||
| 	bool send_tomtou = false, send_writers = false; | ||||
| 	unsigned char *pathname = NULL, *pathbuf = NULL; | ||||
| 
 | ||||
| 	if (!S_ISREG(inode->i_mode) || !ima_initialized) | ||||
| 		return; | ||||
| @ -75,12 +76,27 @@ static void ima_rdwr_violation_check(struct file *file) | ||||
| out: | ||||
| 	mutex_unlock(&inode->i_mutex); | ||||
| 
 | ||||
| 	if (!send_tomtou && !send_writers) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* We will allow 11 spaces for ' (deleted)' to be appended */ | ||||
| 	pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); | ||||
| 	if (pathbuf) { | ||||
| 		pathname = d_path(&file->f_path, pathbuf, PATH_MAX + 11); | ||||
| 		if (IS_ERR(pathname)) | ||||
| 			pathname = NULL; | ||||
| 		else if (strlen(pathname) > IMA_EVENT_NAME_LEN_MAX) | ||||
| 			pathname = NULL; | ||||
| 	} | ||||
| 	if (send_tomtou) | ||||
| 		ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", | ||||
| 				  "ToMToU"); | ||||
| 		ima_add_violation(inode, | ||||
| 				  !pathname ? dentry->d_name.name : pathname, | ||||
| 				  "invalid_pcr", "ToMToU"); | ||||
| 	if (send_writers) | ||||
| 		ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", | ||||
| 				  "open_writers"); | ||||
| 		ima_add_violation(inode, | ||||
| 				  !pathname ? dentry->d_name.name : pathname, | ||||
| 				  "invalid_pcr", "open_writers"); | ||||
| 	kfree(pathbuf); | ||||
| } | ||||
| 
 | ||||
| static void ima_check_last_writer(struct integrity_iint_cache *iint, | ||||
| @ -123,6 +139,7 @@ static int process_measurement(struct file *file, const unsigned char *filename, | ||||
| { | ||||
| 	struct inode *inode = file->f_dentry->d_inode; | ||||
| 	struct integrity_iint_cache *iint; | ||||
| 	unsigned char *pathname = NULL, *pathbuf = NULL; | ||||
| 	int rc = 0; | ||||
| 
 | ||||
| 	if (!ima_initialized || !S_ISREG(inode->i_mode)) | ||||
| @ -147,8 +164,21 @@ retry: | ||||
| 		goto out; | ||||
| 
 | ||||
| 	rc = ima_collect_measurement(iint, file); | ||||
| 	if (!rc) | ||||
| 		ima_store_measurement(iint, file, filename); | ||||
| 	if (rc != 0) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	if (function != BPRM_CHECK) { | ||||
| 		/* We will allow 11 spaces for ' (deleted)' to be appended */ | ||||
| 		pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); | ||||
| 		if (pathbuf) { | ||||
| 			pathname = | ||||
| 			    d_path(&file->f_path, pathbuf, PATH_MAX + 11); | ||||
| 			if (IS_ERR(pathname)) | ||||
| 				pathname = NULL; | ||||
| 		} | ||||
| 	} | ||||
| 	ima_store_measurement(iint, file, !pathname ? filename : pathname); | ||||
| 	kfree(pathbuf); | ||||
| out: | ||||
| 	mutex_unlock(&iint->mutex); | ||||
| 	return rc; | ||||
| @ -228,15 +258,11 @@ static int __init init_ima(void) | ||||
| 	int error; | ||||
| 
 | ||||
| 	error = ima_init(); | ||||
| 	ima_initialized = 1; | ||||
| 	if (!error) | ||||
| 		ima_initialized = 1; | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| static void __exit cleanup_ima(void) | ||||
| { | ||||
| 	ima_cleanup(); | ||||
| } | ||||
| 
 | ||||
| late_initcall(init_ima);	/* Start IMA after the TPM is available */ | ||||
| 
 | ||||
| MODULE_DESCRIPTION("Integrity Measurement Architecture"); | ||||
|  | ||||
| @ -63,6 +63,8 @@ static struct ima_measure_rule_entry default_rules[] = { | ||||
| 	{.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, | ||||
| 	{.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, | ||||
| 	{.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC}, | ||||
| 	{.action = DONT_MEASURE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC}, | ||||
| 	{.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC}, | ||||
| 	{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, | ||||
| 	{.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, | ||||
| 	{.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, | ||||
|  | ||||
| @ -24,7 +24,7 @@ | ||||
|  * | ||||
|  * If successful, 0 will be returned. | ||||
|  */ | ||||
| long compat_keyctl_instantiate_key_iov( | ||||
| static long compat_keyctl_instantiate_key_iov( | ||||
| 	key_serial_t id, | ||||
| 	const struct compat_iovec __user *_payload_iov, | ||||
| 	unsigned ioc, | ||||
| @ -33,7 +33,7 @@ long compat_keyctl_instantiate_key_iov( | ||||
| 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | ||||
| 	long ret; | ||||
| 
 | ||||
| 	if (_payload_iov == 0 || ioc == 0) | ||||
| 	if (!_payload_iov || !ioc) | ||||
| 		goto no_payload; | ||||
| 
 | ||||
| 	ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, | ||||
|  | ||||
| @ -242,7 +242,7 @@ extern long keyctl_instantiate_key_iov(key_serial_t, | ||||
| extern long keyctl_invalidate_key(key_serial_t); | ||||
| 
 | ||||
| extern long keyctl_instantiate_key_common(key_serial_t, | ||||
| 					  const struct iovec __user *, | ||||
| 					  const struct iovec *, | ||||
| 					  unsigned, size_t, key_serial_t); | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
| @ -1106,7 +1106,7 @@ long keyctl_instantiate_key_iov(key_serial_t id, | ||||
| 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | ||||
| 	long ret; | ||||
| 
 | ||||
| 	if (_payload_iov == 0 || ioc == 0) | ||||
| 	if (!_payload_iov || !ioc) | ||||
| 		goto no_payload; | ||||
| 
 | ||||
| 	ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, | ||||
|  | ||||
| @ -751,6 +751,7 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) | ||||
| int __key_link_begin(struct key *keyring, const struct key_type *type, | ||||
| 		     const char *description, unsigned long *_prealloc) | ||||
| 	__acquires(&keyring->sem) | ||||
| 	__acquires(&keyring_serialise_link_sem) | ||||
| { | ||||
| 	struct keyring_list *klist, *nklist; | ||||
| 	unsigned long prealloc; | ||||
| @ -960,6 +961,7 @@ void __key_link(struct key *keyring, struct key *key, | ||||
| void __key_link_end(struct key *keyring, struct key_type *type, | ||||
| 		    unsigned long prealloc) | ||||
| 	__releases(&keyring->sem) | ||||
| 	__releases(&keyring_serialise_link_sem) | ||||
| { | ||||
| 	BUG_ON(type == NULL); | ||||
| 	BUG_ON(type->name == NULL); | ||||
|  | ||||
| @ -43,7 +43,6 @@ struct superblock_smack { | ||||
| 	char		*smk_hat; | ||||
| 	char		*smk_default; | ||||
| 	int		smk_initialized; | ||||
| 	spinlock_t	smk_sblock;	/* for initialization */ | ||||
| }; | ||||
| 
 | ||||
| struct socket_smack { | ||||
| @ -283,6 +282,19 @@ static inline char *smk_of_current(void) | ||||
| 	return smk_of_task(current_security()); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Is the task privileged and allowed to be privileged | ||||
|  * by the onlycap rule. | ||||
|  */ | ||||
| static inline int smack_privileged(int cap) | ||||
| { | ||||
| 	if (!capable(cap)) | ||||
| 		return 0; | ||||
| 	if (smack_onlycap == NULL || smack_onlycap == smk_of_current()) | ||||
| 		return 1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * logging functions | ||||
|  */ | ||||
|  | ||||
| @ -220,14 +220,9 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Return if a specific label has been designated as the | ||||
| 	 * only one that gets privilege and current does not | ||||
| 	 * have that label. | ||||
| 	 * Allow for priviliged to override policy. | ||||
| 	 */ | ||||
| 	if (smack_onlycap != NULL && smack_onlycap != sp) | ||||
| 		goto out_audit; | ||||
| 
 | ||||
| 	if (capable(CAP_MAC_OVERRIDE)) | ||||
| 	if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE)) | ||||
| 		rc = 0; | ||||
| 
 | ||||
| out_audit: | ||||
|  | ||||
| @ -217,7 +217,7 @@ static int smack_syslog(int typefrom_file) | ||||
| 	int rc = 0; | ||||
| 	char *sp = smk_of_current(); | ||||
| 
 | ||||
| 	if (capable(CAP_MAC_OVERRIDE)) | ||||
| 	if (smack_privileged(CAP_MAC_OVERRIDE)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	 if (sp != smack_known_floor.smk_known) | ||||
| @ -251,7 +251,6 @@ static int smack_sb_alloc_security(struct super_block *sb) | ||||
| 	sbsp->smk_floor = smack_known_floor.smk_known; | ||||
| 	sbsp->smk_hat = smack_known_hat.smk_known; | ||||
| 	sbsp->smk_initialized = 0; | ||||
| 	spin_lock_init(&sbsp->smk_sblock); | ||||
| 
 | ||||
| 	sb->s_security = sbsp; | ||||
| 
 | ||||
| @ -332,13 +331,10 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | ||||
| 	char *commap; | ||||
| 	char *nsp; | ||||
| 
 | ||||
| 	spin_lock(&sp->smk_sblock); | ||||
| 	if (sp->smk_initialized != 0) { | ||||
| 		spin_unlock(&sp->smk_sblock); | ||||
| 	if (sp->smk_initialized != 0) | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	sp->smk_initialized = 1; | ||||
| 	spin_unlock(&sp->smk_sblock); | ||||
| 
 | ||||
| 	for (op = data; op != NULL; op = commap) { | ||||
| 		commap = strchr(op, ','); | ||||
| @ -825,7 +821,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | ||||
| 	    strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | ||||
| 	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | ||||
| 	    strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | ||||
| 		if (!capable(CAP_MAC_ADMIN)) | ||||
| 		if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 			rc = -EPERM; | ||||
| 		/*
 | ||||
| 		 * check label validity here so import wont fail on | ||||
| @ -835,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | ||||
| 		    smk_import(value, size) == NULL) | ||||
| 			rc = -EINVAL; | ||||
| 	} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | ||||
| 		if (!capable(CAP_MAC_ADMIN)) | ||||
| 		if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 			rc = -EPERM; | ||||
| 		if (size != TRANS_TRUE_SIZE || | ||||
| 		    strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) | ||||
| @ -931,7 +927,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | ||||
| 	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | ||||
| 	    strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || | ||||
| 	    strcmp(name, XATTR_NAME_SMACKMMAP)) { | ||||
| 		if (!capable(CAP_MAC_ADMIN)) | ||||
| 		if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 			rc = -EPERM; | ||||
| 	} else | ||||
| 		rc = cap_inode_removexattr(dentry, name); | ||||
| @ -1720,7 +1716,8 @@ static int smack_task_wait(struct task_struct *p) | ||||
| 	 * state into account in the decision as well as | ||||
| 	 * the smack value. | ||||
| 	 */ | ||||
| 	if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE)) | ||||
| 	if (smack_privileged(CAP_MAC_OVERRIDE) || | ||||
| 	    has_capability(p, CAP_MAC_OVERRIDE)) | ||||
| 		rc = 0; | ||||
| 	/* we log only if we didn't get overriden */ | ||||
|  out_log: | ||||
| @ -2721,7 +2718,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, | ||||
| 	if (p != current) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	if (value == NULL || size == 0 || size >= SMK_LONGLABEL) | ||||
| @ -2784,7 +2781,7 @@ static int smack_unix_stream_connect(struct sock *sock, | ||||
| 	smk_ad_setfield_u_net_sk(&ad, other); | ||||
| #endif | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_OVERRIDE)) | ||||
| 	if (!smack_privileged(CAP_MAC_OVERRIDE)) | ||||
| 		rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -2820,7 +2817,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | ||||
| 	smk_ad_setfield_u_net_sk(&ad, other->sk); | ||||
| #endif | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_OVERRIDE)) | ||||
| 	if (!smack_privileged(CAP_MAC_OVERRIDE)) | ||||
| 		rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | ||||
| 
 | ||||
| 	return rc; | ||||
|  | ||||
| @ -215,28 +215,27 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, | ||||
|  * @access: access string | ||||
|  * @rule: Smack rule | ||||
|  * @import: if non-zero, import labels | ||||
|  * @len: label length limit | ||||
|  * | ||||
|  * Returns 0 on success, -1 on failure | ||||
|  */ | ||||
| static int smk_fill_rule(const char *subject, const char *object, | ||||
| 				const char *access, struct smack_rule *rule, | ||||
| 				int import) | ||||
| 				int import, int len) | ||||
| { | ||||
| 	int rc = -1; | ||||
| 	int done; | ||||
| 	const char *cp; | ||||
| 	struct smack_known *skp; | ||||
| 
 | ||||
| 	if (import) { | ||||
| 		rule->smk_subject = smk_import(subject, 0); | ||||
| 		rule->smk_subject = smk_import(subject, len); | ||||
| 		if (rule->smk_subject == NULL) | ||||
| 			return -1; | ||||
| 
 | ||||
| 		rule->smk_object = smk_import(object, 0); | ||||
| 		rule->smk_object = smk_import(object, len); | ||||
| 		if (rule->smk_object == NULL) | ||||
| 			return -1; | ||||
| 	} else { | ||||
| 		cp = smk_parse_smack(subject, 0); | ||||
| 		cp = smk_parse_smack(subject, len); | ||||
| 		if (cp == NULL) | ||||
| 			return -1; | ||||
| 		skp = smk_find_entry(cp); | ||||
| @ -245,7 +244,7 @@ static int smk_fill_rule(const char *subject, const char *object, | ||||
| 			return -1; | ||||
| 		rule->smk_subject = skp->smk_known; | ||||
| 
 | ||||
| 		cp = smk_parse_smack(object, 0); | ||||
| 		cp = smk_parse_smack(object, len); | ||||
| 		if (cp == NULL) | ||||
| 			return -1; | ||||
| 		skp = smk_find_entry(cp); | ||||
| @ -257,7 +256,7 @@ static int smk_fill_rule(const char *subject, const char *object, | ||||
| 
 | ||||
| 	rule->smk_access = 0; | ||||
| 
 | ||||
| 	for (cp = access, done = 0; *cp && !done; cp++) { | ||||
| 	for (cp = access; *cp != '\0'; cp++) { | ||||
| 		switch (*cp) { | ||||
| 		case '-': | ||||
| 			break; | ||||
| @ -282,13 +281,11 @@ static int smk_fill_rule(const char *subject, const char *object, | ||||
| 			rule->smk_access |= MAY_TRANSMUTE; | ||||
| 			break; | ||||
| 		default: | ||||
| 			done = 1; | ||||
| 			break; | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	rc = 0; | ||||
| 
 | ||||
| 	return rc; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| @ -304,7 +301,8 @@ static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) | ||||
| 	int rc; | ||||
| 
 | ||||
| 	rc = smk_fill_rule(data, data + SMK_LABELLEN, | ||||
| 			   data + SMK_LABELLEN + SMK_LABELLEN, rule, import); | ||||
| 			   data + SMK_LABELLEN + SMK_LABELLEN, rule, import, | ||||
| 			   SMK_LABELLEN); | ||||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| @ -340,7 +338,7 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule, | ||||
| 		goto free_out_o; | ||||
| 
 | ||||
| 	if (sscanf(data, "%s %s %s", subject, object, access) == 3) | ||||
| 		rc = smk_fill_rule(subject, object, access, rule, import); | ||||
| 		rc = smk_fill_rule(subject, object, access, rule, import, 0); | ||||
| 
 | ||||
| 	kfree(access); | ||||
| free_out_o: | ||||
| @ -520,6 +518,9 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | ||||
| 	if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (srp->smk_access == 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object); | ||||
| 
 | ||||
| 	seq_putc(s, ' '); | ||||
| @ -534,8 +535,6 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | ||||
| 		seq_putc(s, 'a'); | ||||
| 	if (srp->smk_access & MAY_TRANSMUTE) | ||||
| 		seq_putc(s, 't'); | ||||
| 	if (srp->smk_access == 0) | ||||
| 		seq_putc(s, '-'); | ||||
| 
 | ||||
| 	seq_putc(s, '\n'); | ||||
| } | ||||
| @ -595,13 +594,12 @@ static int smk_open_load(struct inode *inode, struct file *file) | ||||
| static ssize_t smk_write_load(struct file *file, const char __user *buf, | ||||
| 			      size_t count, loff_t *ppos) | ||||
| { | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Must have privilege. | ||||
| 	 * No partial writes. | ||||
| 	 * Enough data must be present. | ||||
| 	 */ | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, | ||||
| @ -787,7 +785,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, | ||||
| 	 * No partial writes. | ||||
| 	 * Enough data must be present. | ||||
| 	 */ | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 	if (*ppos != 0) | ||||
| 		return -EINVAL; | ||||
| @ -1090,7 +1088,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | ||||
| 	 * "<addr/mask, as a.b.c.d/e><space><label>" | ||||
| 	 * "<addr, as a.b.c.d><space><label>" | ||||
| 	 */ | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 	if (*ppos != 0) | ||||
| 		return -EINVAL; | ||||
| @ -1267,7 +1265,7 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf, | ||||
| 	char temp[80]; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	if (count >= sizeof(temp) || count == 0) | ||||
| @ -1334,7 +1332,7 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf, | ||||
| 	char temp[80]; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	if (count >= sizeof(temp) || count == 0) | ||||
| @ -1412,7 +1410,7 @@ static ssize_t smk_write_mapped(struct file *file, const char __user *buf, | ||||
| 	char temp[80]; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	if (count >= sizeof(temp) || count == 0) | ||||
| @ -1503,7 +1501,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, | ||||
| 	char *data; | ||||
| 	int rc = count; | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	data = kzalloc(count + 1, GFP_KERNEL); | ||||
| @ -1586,7 +1584,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | ||||
| 	char *sp = smk_of_task(current->cred->security); | ||||
| 	int rc = count; | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -1664,7 +1662,7 @@ static ssize_t smk_write_logging(struct file *file, const char __user *buf, | ||||
| 	char temp[32]; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	if (count >= sizeof(temp) || count == 0) | ||||
| @ -1885,7 +1883,7 @@ static ssize_t smk_write_load2(struct file *file, const char __user *buf, | ||||
| 	/*
 | ||||
| 	 * Must have privilege. | ||||
| 	 */ | ||||
| 	if (!capable(CAP_MAC_ADMIN)) | ||||
| 	if (!smack_privileged(CAP_MAC_ADMIN)) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, | ||||
| @ -2051,7 +2049,6 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | ||||
| 	} | ||||
| 
 | ||||
| 	root_inode = sb->s_root->d_inode; | ||||
| 	root_inode->i_security = new_inode_smack(smack_known_floor.smk_known); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user