diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 18:49:06 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 18:49:06 -0700 |
commit | e05644e17e744315bce12b0948cdc36910b9a76e (patch) | |
tree | 92d62ff59c57f991ef6b5c3cc2c2dcd205946a11 | |
parent | 97e7292ab5ccd30a13c3612835535fc3f3e59715 (diff) | |
parent | 663728418e3494f8e4a82f5d1b2f23c22d11be35 (diff) | |
download | op-kernel-dev-e05644e17e744315bce12b0948cdc36910b9a76e.zip op-kernel-dev-e05644e17e744315bce12b0948cdc36910b9a76e.tar.gz |
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)"
...
38 files changed, 153 insertions, 2168 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index fe2fa33..3086d4b 100644 --- a/MAINTAINERS +++ b/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 diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index ae43ac5..817f0ee 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -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); diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 76da32e..3251a44 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -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"); diff --git a/lib/Kconfig b/lib/Kconfig index a9e1540..8269d56 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -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 diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile index 567d52e..45ca90a 100644 --- a/lib/mpi/Makefile +++ b/lib/mpi/Makefile @@ -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 diff --git a/lib/mpi/generic_mpi-asm-defs.h b/lib/mpi/generic_mpi-asm-defs.h deleted file mode 100644 index 047d1f5..0000000 --- a/lib/mpi/generic_mpi-asm-defs.h +++ /dev/null @@ -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) diff --git a/lib/mpi/mpi-add.c b/lib/mpi/mpi-add.c deleted file mode 100644 index f56b9ba..0000000 --- a/lib/mpi/mpi-add.c +++ /dev/null @@ -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; -} diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c index 0c50536..5687248 100644 --- a/lib/mpi/mpi-bit.c +++ b/lib/mpi/mpi-bit.c @@ -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; -} diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c deleted file mode 100644 index 914bc42..0000000 --- a/lib/mpi/mpi-cmp.c +++ /dev/null @@ -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; -} diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c deleted file mode 100644 index f68cbbb..0000000 --- a/lib/mpi/mpi-div.c +++ /dev/null @@ -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); -} diff --git a/lib/mpi/mpi-gcd.c b/lib/mpi/mpi-gcd.c deleted file mode 100644 index 13c48ae..0000000 --- a/lib/mpi/mpi-gcd.c +++ /dev/null @@ -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; -} diff --git a/lib/mpi/mpi-inline.c b/lib/mpi/mpi-inline.c deleted file mode 100644 index 654f68a..0000000 --- a/lib/mpi/mpi-inline.c +++ /dev/null @@ -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" diff --git a/lib/mpi/mpi-inv.c b/lib/mpi/mpi-inv.c deleted file mode 100644 index 0951f98..0000000 --- a/lib/mpi/mpi-inv.c +++ /dev/null @@ -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; -} diff --git a/lib/mpi/mpi-mpow.c b/lib/mpi/mpi-mpow.c deleted file mode 100644 index 7328d0d..0000000 --- a/lib/mpi/mpi-mpow.c +++ /dev/null @@ -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; -} diff --git a/lib/mpi/mpi-mul.c b/lib/mpi/mpi-mul.c deleted file mode 100644 index 1f3219e..0000000 --- a/lib/mpi/mpi-mul.c +++ /dev/null @@ -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); -} diff --git a/lib/mpi/mpi-scan.c b/lib/mpi/mpi-scan.c deleted file mode 100644 index b2da5ad..0000000 --- a/lib/mpi/mpi-scan.c +++ /dev/null @@ -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; - -} diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index f26b41f..f0fa659 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -74,81 +74,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 * return string (This function does return a 0 byte buffer with NBYTES diff --git a/lib/mpi/mpih-div.c b/lib/mpi/mpih-div.c index cde1aae..c57d1d4 100644 --- a/lib/mpi/mpih-div.c +++ b/lib/mpi/mpih-div.c @@ -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; - } -} diff --git a/lib/mpi/mpih-mul.c b/lib/mpi/mpih-mul.c index c69c5ee..7c84171 100644 --- a/lib/mpi/mpih-mul.c +++ b/lib/mpi/mpih-mul.c @@ -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, diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c index 26e4ed3..657979f 100644 --- a/lib/mpi/mpiutil.c +++ b/lib/mpi/mpiutil.c @@ -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; -} diff --git a/samples/seccomp/.gitignore b/samples/seccomp/.gitignore new file mode 100644 index 0000000..78fb781 --- /dev/null +++ b/samples/seccomp/.gitignore @@ -0,0 +1,3 @@ +bpf-direct +bpf-fancy +dropper diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 35664fe..b9c1219 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -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 diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 5690c02..5f740f6 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -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 diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 3ccf7ac..e7c99fd 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -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); diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 88a2788..032ff03 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -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) diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c index 21e96bf..7a57f67 100644 --- a/security/integrity/ima/ima_audit.c +++ b/security/integrity/ima/ima_audit.c @@ -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, diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index e1aa2b4..38477c9 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -367,20 +367,11 @@ int __init ima_fs_init(void) return 0; out: - securityfs_remove(runtime_measurements_count); - securityfs_remove(ascii_runtime_measurements); - securityfs_remove(binary_runtime_measurements); - securityfs_remove(ima_dir); - 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); + return -1; } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 17f1f06..b5dfd53 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -90,8 +90,3 @@ int __init ima_init(void) return ima_fs_init(); } - -void __exit ima_cleanup(void) -{ - ima_fs_cleanup(); -} diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b17be79..be82949 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -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"); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index d8edff2..1a95830 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -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, diff --git a/security/keys/compat.c b/security/keys/compat.c index c92d42b..1c26176 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -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, diff --git a/security/keys/internal.h b/security/keys/internal.h index c246ba5..22ff052 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -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); /* diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index f1b59ae..3364fbf 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -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, diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 7445875..81e7852 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -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); diff --git a/security/smack/smack.h b/security/smack/smack.h index cc361b8..99b3612 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -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 { @@ -284,6 +283,19 @@ static inline char *smk_of_current(void) } /* + * 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 */ #define SMACK_AUDIT_DENIED 0x1 diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 9f3705e..db14689 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -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: diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index ee0bb57..8221514 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -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; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 1810c9a..d31e6d9 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -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; } |