summaryrefslogtreecommitdiff
path: root/mpz/powm_sec.c
diff options
context:
space:
mode:
authorTorbjorn Granlund <tege@gmplib.org>2009-12-23 05:30:08 +0100
committerTorbjorn Granlund <tege@gmplib.org>2009-12-23 05:30:08 +0100
commit857b60452cc26bd4705a0a0ed5a99e5b7d32539a (patch)
tree664a8801c854b737df459c8dc725a3a3ae108441 /mpz/powm_sec.c
parent09103509a876320e3e5b26bc0644a632a0326f6f (diff)
downloadgmp-857b60452cc26bd4705a0a0ed5a99e5b7d32539a.tar.gz
Add function mpz_powm_sec.
Diffstat (limited to 'mpz/powm_sec.c')
-rw-r--r--mpz/powm_sec.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/mpz/powm_sec.c b/mpz/powm_sec.c
new file mode 100644
index 000000000..2432fe498
--- /dev/null
+++ b/mpz/powm_sec.c
@@ -0,0 +1,90 @@
+/* mpz_powm_sec(res,base,exp,mod) -- Set R to (U^E) mod M.
+
+ Contributed to the GNU project by Torbjorn Granlund.
+
+Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2002, 2005, 2008, 2009
+Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP 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 3 of the License, or (at your
+option) any later version.
+
+The GNU MP 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 GNU MP Library. If not, see http://www.gnu.org/licenses/. */
+
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+
+void
+mpz_powm_sec (mpz_ptr r, mpz_srcptr b, mpz_srcptr e, mpz_srcptr m)
+{
+ mp_size_t n;
+ mp_ptr rp, tp;
+ mp_srcptr bp, ep, mp;
+ mp_size_t rn, bn, es, en;
+ TMP_DECL;
+
+ n = ABSIZ(m);
+ if (n == 0)
+ DIVIDE_BY_ZERO;
+
+ mp = PTR(m);
+
+ if (mp[0] % 2 == 0)
+ DIVIDE_BY_ZERO;
+
+ es = SIZ(e);
+ if (UNLIKELY (es <= 0))
+ {
+ mpz_t new_b;
+ if (es == 0)
+ {
+ /* b^0 mod m, b is anything and m is non-zero.
+ Result is 1 mod m, i.e., 1 or 0 depending on if m = 1. */
+ SIZ(r) = n != 1 || mp[0] != 1;
+ PTR(r)[0] = 1;
+ return;
+ }
+ DIVIDE_BY_ZERO;
+ }
+
+ en = es;
+ bn = ABSIZ(b);
+
+ TMP_MARK;
+ tp = TMP_ALLOC_LIMBS (n + mpn_powm_sec_itch (bn, en, n));
+
+ rp = tp; tp += n;
+
+ bp = PTR(b);
+ ep = PTR(e);
+
+ mpn_powm_sec (rp, bp, bn, ep, en, mp, n, tp);
+
+ rn = n;
+
+ MPN_NORMALIZE (rp, rn);
+
+ if ((ep[0] & 1) && SIZ(b) < 0 && rn != 0)
+ {
+ mpn_sub (rp, PTR(m), n, rp, rn);
+ rn = n;
+ MPN_NORMALIZE (rp, rn);
+ }
+
+ MPZ_REALLOC (r, rn);
+ SIZ(r) = rn;
+ MPN_COPY (PTR(r), rp, rn);
+
+ TMP_FREE;
+}