bn_mp_exptmod.c 2.84 KB
Newer Older
1
#include "tommath_private.h"
2 3 4 5 6 7 8 9 10 11
#ifdef BN_MP_EXPTMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
12
 * SPDX-License-Identifier: Unlicense
13 14 15 16 17 18 19 20
 */


/* this is a shell function that calls either the normal or Montgomery
 * exptmod functions.  Originally the call to the montgomery code was
 * embedded in the normal function but that wasted alot of stack space
 * for nothing (since 99% of the time the Montgomery code would be called)
 */
21
int mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y)
22
{
23
   int dr;
24

25 26 27 28
   /* modulus P must be positive */
   if (P->sign == MP_NEG) {
      return MP_VAL;
   }
29

30 31
   /* if exponent X is negative we have to recurse */
   if (X->sign == MP_NEG) {
32
#ifdef BN_MP_INVMOD_C
33 34
      mp_int tmpG, tmpX;
      int err;
35

36 37 38 39 40 41 42 43
      /* first compute 1/G mod P */
      if ((err = mp_init(&tmpG)) != MP_OKAY) {
         return err;
      }
      if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
         mp_clear(&tmpG);
         return err;
      }
44

45 46 47 48 49 50 51 52 53
      /* now get |X| */
      if ((err = mp_init(&tmpX)) != MP_OKAY) {
         mp_clear(&tmpG);
         return err;
      }
      if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
         mp_clear_multi(&tmpG, &tmpX, NULL);
         return err;
      }
54

55 56 57 58 59 60 61
      /* and now compute (1/G)**|X| instead of G**X [X < 0] */
      err = mp_exptmod(&tmpG, &tmpX, P, Y);
      mp_clear_multi(&tmpG, &tmpX, NULL);
      return err;
#else
      /* no invmod */
      return MP_VAL;
62
#endif
63
   }
64

65
   /* modified diminished radix reduction */
66
#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
67 68 69
   if (mp_reduce_is_2k_l(P) == MP_YES) {
      return s_mp_exptmod(G, X, P, Y, 1);
   }
70 71 72
#endif

#ifdef BN_MP_DR_IS_MODULUS_C
73 74
   /* is it a DR modulus? */
   dr = mp_dr_is_modulus(P);
75
#else
76 77
   /* default to no */
   dr = 0;
78 79 80
#endif

#ifdef BN_MP_REDUCE_IS_2K_C
81 82 83 84
   /* if not, is it a unrestricted DR modulus? */
   if (dr == 0) {
      dr = mp_reduce_is_2k(P) << 1;
   }
85
#endif
86 87

   /* if the modulus is odd or dr != 0 use the montgomery method */
88
#ifdef BN_MP_EXPTMOD_FAST_C
89 90 91
   if ((mp_isodd(P) == MP_YES) || (dr !=  0)) {
      return mp_exptmod_fast(G, X, P, Y, dr);
   } else {
92 93
#endif
#ifdef BN_S_MP_EXPTMOD_C
94 95
      /* otherwise use the generic Barrett reduction technique */
      return s_mp_exptmod(G, X, P, Y, 0);
96
#else
97 98
      /* no exptmod for evens */
      return MP_VAL;
99 100
#endif
#ifdef BN_MP_EXPTMOD_FAST_C
101
   }
102 103 104 105 106
#endif
}

#endif

107 108 109
/* ref:         HEAD -> master, tag: v1.1.0 */
/* git commit:  08549ad6bc8b0cede0b357a9c341c5c6473a9c55 */
/* commit time: 2019-01-28 20:32:32 +0100 */