summaryrefslogtreecommitdiff
path: root/ecc-mod.c
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2013-02-15 09:47:14 +0100
committerNiels Möller <nisse@lysator.liu.se>2013-02-15 09:47:14 +0100
commit9422a55130ba65f73a053f063efa6226f945b4f1 (patch)
treec35c54d1a5762aa41ad7fd5b85b32181da0f78a3 /ecc-mod.c
parent75a1291ed08198f75140bdbb52b317f39e60d4ca (diff)
downloadnettle-9422a55130ba65f73a053f063efa6226f945b4f1.tar.gz
Integrated ECC internals.
Diffstat (limited to 'ecc-mod.c')
-rw-r--r--ecc-mod.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/ecc-mod.c b/ecc-mod.c
new file mode 100644
index 00000000..1d2f4232
--- /dev/null
+++ b/ecc-mod.c
@@ -0,0 +1,102 @@
+/* ecc-mod.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013 Niels Möller
+ *
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The nettle library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+/* Development of Nettle's ECC support was funded by Internetfonden. */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "ecc-internal.h"
+
+/* Computes r mod m, where m is of size mn. bp holds B^mn mod m, as mn
+ limbs, but the upper mn - bn libms are zero. */
+void
+ecc_mod (mp_limb_t *rp, mp_size_t rn, mp_size_t mn,
+ const mp_limb_t *bp, mp_size_t bn,
+ const mp_limb_t *b_shifted, unsigned shift)
+{
+ mp_limb_t hi;
+ mp_size_t sn = mn - bn;
+ mp_size_t i;
+
+ assert (sn > 0);
+
+ /* FIXME: Could use mpn_addmul_2. */
+ /* Eliminate sn = mn - bn limbs at a time */
+ if (bp[bn-1] < ((mp_limb_t) 1 << (GMP_NUMB_BITS - 1)))
+ {
+ /* Multiply sn + 1 limbs at a time, so we get a mn+1 limb
+ product. Then we can absorb the carry in the high limb */
+ while (rn > 2 * mn - bn)
+ {
+ rn -= sn;
+
+ for (i = 0; i <= sn; i++)
+ rp[rn+i-1] = mpn_addmul_1 (rp + rn - mn - 1 + i, bp, bn, rp[rn+i-1]);
+ rp[rn-1] = rp[rn+sn-1]
+ + mpn_add_n (rp + rn - sn - 1, rp + rn - sn - 1, rp + rn - 1, sn);
+ }
+ goto final_limbs;
+ }
+ else
+ {
+ while (rn >= 2 * mn - bn)
+ {
+ rn -= sn;
+
+ for (i = 0; i < sn; i++)
+ rp[rn+i] = mpn_addmul_1 (rp + rn - mn + i, bp, bn, rp[rn+i]);
+
+ hi = mpn_add_n (rp + rn - sn, rp + rn - sn, rp + rn, sn);
+ hi = cnd_add_n (hi, rp + rn - mn, bp, mn);
+ assert (hi == 0);
+ }
+ }
+
+ if (rn > mn)
+ {
+ final_limbs:
+ sn = rn - mn;
+
+ for (i = 0; i < sn; i++)
+ rp[mn+i] = mpn_addmul_1 (rp + i, bp, bn, rp[mn+i]);
+
+ hi = mpn_add_n (rp + bn, rp + bn, rp + mn, sn);
+ hi = sec_add_1 (rp + bn + sn, rp + bn + sn, mn - bn - sn, hi);
+ }
+
+ if (shift > 0)
+ {
+ /* Combine hi with top bits, add in */
+ hi = (hi << shift) | (rp[mn-1] >> (GMP_NUMB_BITS - shift));
+ rp[mn-1] = (rp[mn-1] & (((mp_limb_t) 1 << (GMP_NUMB_BITS - shift)) - 1))
+ + mpn_addmul_1 (rp, b_shifted, mn-1, hi);
+ }
+ else
+ {
+ hi = cnd_add_n (hi, rp, bp, mn);
+ assert (hi == 0);
+ }
+}