mpi-inv.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* mpi-inv.c - MPI functions
  2. * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  3. *
  4. * This file is part of GnuPG.
  5. *
  6. * GnuPG is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GnuPG is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  19. */
  20. #include "mpi-internal.h"
  21. /****************
  22. * Calculate the multiplicative inverse X of A mod N
  23. * That is: Find the solution x for
  24. * 1 = (a*x) mod n
  25. */
  26. int mpi_invm(MPI x, const MPI a, const MPI n)
  27. {
  28. /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
  29. * modified according to Michael Penk's solution for Exercice 35
  30. * with further enhancement */
  31. MPI u = NULL, v = NULL;
  32. MPI u1 = NULL, u2 = NULL, u3 = NULL;
  33. MPI v1 = NULL, v2 = NULL, v3 = NULL;
  34. MPI t1 = NULL, t2 = NULL, t3 = NULL;
  35. unsigned k;
  36. int sign;
  37. int odd = 0;
  38. int rc = -ENOMEM;
  39. if (mpi_copy(&u, a) < 0)
  40. goto cleanup;
  41. if (mpi_copy(&v, n) < 0)
  42. goto cleanup;
  43. for (k = 0; !mpi_test_bit(u, 0) && !mpi_test_bit(v, 0); k++) {
  44. if (mpi_rshift(u, u, 1) < 0)
  45. goto cleanup;
  46. if (mpi_rshift(v, v, 1) < 0)
  47. goto cleanup;
  48. }
  49. odd = mpi_test_bit(v, 0);
  50. u1 = mpi_alloc_set_ui(1);
  51. if (!u1)
  52. goto cleanup;
  53. if (!odd) {
  54. u2 = mpi_alloc_set_ui(0);
  55. if (!u2)
  56. goto cleanup;
  57. }
  58. if (mpi_copy(&u3, u) < 0)
  59. goto cleanup;
  60. if (mpi_copy(&v1, v) < 0)
  61. goto cleanup;
  62. if (!odd) {
  63. v2 = mpi_alloc(mpi_get_nlimbs(u));
  64. if (!v2)
  65. goto cleanup;
  66. if (mpi_sub(v2, u1, u) < 0)
  67. goto cleanup; /* U is used as const 1 */
  68. }
  69. if (mpi_copy(&v3, v) < 0)
  70. goto cleanup;
  71. if (mpi_test_bit(u, 0)) { /* u is odd */
  72. t1 = mpi_alloc_set_ui(0);
  73. if (!t1)
  74. goto cleanup;
  75. if (!odd) {
  76. t2 = mpi_alloc_set_ui(1);
  77. if (!t2)
  78. goto cleanup;
  79. t2->sign = 1;
  80. }
  81. if (mpi_copy(&t3, v) < 0)
  82. goto cleanup;
  83. t3->sign = !t3->sign;
  84. goto Y4;
  85. } else {
  86. t1 = mpi_alloc_set_ui(1);
  87. if (!t1)
  88. goto cleanup;
  89. if (!odd) {
  90. t2 = mpi_alloc_set_ui(0);
  91. if (!t2)
  92. goto cleanup;
  93. }
  94. if (mpi_copy(&t3, u) < 0)
  95. goto cleanup;
  96. }
  97. do {
  98. do {
  99. if (!odd) {
  100. if (mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0)) { /* one is odd */
  101. if (mpi_add(t1, t1, v) < 0)
  102. goto cleanup;
  103. if (mpi_sub(t2, t2, u) < 0)
  104. goto cleanup;
  105. }
  106. if (mpi_rshift(t1, t1, 1) < 0)
  107. goto cleanup;
  108. if (mpi_rshift(t2, t2, 1) < 0)
  109. goto cleanup;
  110. if (mpi_rshift(t3, t3, 1) < 0)
  111. goto cleanup;
  112. } else {
  113. if (mpi_test_bit(t1, 0))
  114. if (mpi_add(t1, t1, v) < 0)
  115. goto cleanup;
  116. if (mpi_rshift(t1, t1, 1) < 0)
  117. goto cleanup;
  118. if (mpi_rshift(t3, t3, 1) < 0)
  119. goto cleanup;
  120. }
  121. Y4:
  122. ;
  123. } while (!mpi_test_bit(t3, 0)); /* while t3 is even */
  124. if (!t3->sign) {
  125. if (mpi_set(u1, t1) < 0)
  126. goto cleanup;
  127. if (!odd)
  128. if (mpi_set(u2, t2) < 0)
  129. goto cleanup;
  130. if (mpi_set(u3, t3) < 0)
  131. goto cleanup;
  132. } else {
  133. if (mpi_sub(v1, v, t1) < 0)
  134. goto cleanup;
  135. sign = u->sign;
  136. u->sign = !u->sign;
  137. if (!odd)
  138. if (mpi_sub(v2, u, t2) < 0)
  139. goto cleanup;
  140. u->sign = sign;
  141. sign = t3->sign;
  142. t3->sign = !t3->sign;
  143. if (mpi_set(v3, t3) < 0)
  144. goto cleanup;
  145. t3->sign = sign;
  146. }
  147. if (mpi_sub(t1, u1, v1) < 0)
  148. goto cleanup;
  149. if (!odd)
  150. if (mpi_sub(t2, u2, v2) < 0)
  151. goto cleanup;
  152. if (mpi_sub(t3, u3, v3) < 0)
  153. goto cleanup;
  154. if (t1->sign) {
  155. if (mpi_add(t1, t1, v) < 0)
  156. goto cleanup;
  157. if (!odd)
  158. if (mpi_sub(t2, t2, u) < 0)
  159. goto cleanup;
  160. }
  161. } while (mpi_cmp_ui(t3, 0)); /* while t3 != 0 */
  162. /* mpi_lshift( u3, k ); */
  163. rc = mpi_set(x, u1);
  164. cleanup:
  165. mpi_free(u1);
  166. mpi_free(v1);
  167. mpi_free(t1);
  168. if (!odd) {
  169. mpi_free(u2);
  170. mpi_free(v2);
  171. mpi_free(t2);
  172. }
  173. mpi_free(u3);
  174. mpi_free(v3);
  175. mpi_free(t3);
  176. mpi_free(u);
  177. mpi_free(v);
  178. return rc;
  179. }