bn_mp_exptmod.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #include <tommath.h>
  2. #ifdef BN_MP_EXPTMOD_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4. *
  5. * LibTomMath is a library that provides multiple-precision
  6. * integer arithmetic as well as number theoretic functionality.
  7. *
  8. * The library was designed directly after the MPI library by
  9. * Michael Fromberger but has been written from scratch with
  10. * additional optimizations in place.
  11. *
  12. * The library is free for all purposes without any express
  13. * guarantee it works.
  14. *
  15. * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
  16. */
  17. /* this is a shell function that calls either the normal or Montgomery
  18. * exptmod functions. Originally the call to the montgomery code was
  19. * embedded in the normal function but that wasted alot of stack space
  20. * for nothing (since 99% of the time the Montgomery code would be called)
  21. */
  22. int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
  23. {
  24. int dr;
  25. /* modulus P must be positive */
  26. if (P->sign == MP_NEG) {
  27. return MP_VAL;
  28. }
  29. /* if exponent X is negative we have to recurse */
  30. if (X->sign == MP_NEG) {
  31. #ifdef BN_MP_INVMOD_C
  32. mp_int tmpG, tmpX;
  33. int err;
  34. /* first compute 1/G mod P */
  35. if ((err = mp_init(&tmpG)) != MP_OKAY) {
  36. return err;
  37. }
  38. if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
  39. mp_clear(&tmpG);
  40. return err;
  41. }
  42. /* now get |X| */
  43. if ((err = mp_init(&tmpX)) != MP_OKAY) {
  44. mp_clear(&tmpG);
  45. return err;
  46. }
  47. if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
  48. mp_clear_multi(&tmpG, &tmpX, NULL);
  49. return err;
  50. }
  51. /* and now compute (1/G)**|X| instead of G**X [X < 0] */
  52. err = mp_exptmod(&tmpG, &tmpX, P, Y);
  53. mp_clear_multi(&tmpG, &tmpX, NULL);
  54. return err;
  55. #else
  56. /* no invmod */
  57. return MP_VAL;
  58. #endif
  59. }
  60. /* modified diminished radix reduction */
  61. #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
  62. if (mp_reduce_is_2k_l(P) == MP_YES) {
  63. return s_mp_exptmod(G, X, P, Y, 1);
  64. }
  65. #endif
  66. #ifdef BN_MP_DR_IS_MODULUS_C
  67. /* is it a DR modulus? */
  68. dr = mp_dr_is_modulus(P);
  69. #else
  70. /* default to no */
  71. dr = 0;
  72. #endif
  73. #ifdef BN_MP_REDUCE_IS_2K_C
  74. /* if not, is it a unrestricted DR modulus? */
  75. if (dr == 0) {
  76. dr = mp_reduce_is_2k(P) << 1;
  77. }
  78. #endif
  79. /* if the modulus is odd or dr != 0 use the montgomery method */
  80. #ifdef BN_MP_EXPTMOD_FAST_C
  81. if (mp_isodd (P) == 1 || dr != 0) {
  82. return mp_exptmod_fast (G, X, P, Y, dr);
  83. } else {
  84. #endif
  85. #ifdef BN_S_MP_EXPTMOD_C
  86. /* otherwise use the generic Barrett reduction technique */
  87. return s_mp_exptmod (G, X, P, Y, 0);
  88. #else
  89. /* no exptmod for evens */
  90. return MP_VAL;
  91. #endif
  92. #ifdef BN_MP_EXPTMOD_FAST_C
  93. }
  94. #endif
  95. }
  96. #endif
  97. /* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */
  98. /* $Revision: 1.4 $ */
  99. /* $Date: 2006/03/31 14:18:44 $ */