mpi-mod.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* mpi-mod.c - Modular reduction
  2. * Copyright (C) 1998, 1999, 2001, 2002, 2003,
  3. * 2007 Free Software Foundation, Inc.
  4. *
  5. * This file is part of Libgcrypt.
  6. */
  7. #include "mpi-internal.h"
  8. #include "longlong.h"
  9. /* Context used with Barrett reduction. */
  10. struct barrett_ctx_s {
  11. MPI m; /* The modulus - may not be modified. */
  12. int m_copied; /* If true, M needs to be released. */
  13. int k;
  14. MPI y;
  15. MPI r1; /* Helper MPI. */
  16. MPI r2; /* Helper MPI. */
  17. MPI r3; /* Helper MPI allocated on demand. */
  18. };
  19. void mpi_mod(MPI rem, MPI dividend, MPI divisor)
  20. {
  21. mpi_fdiv_r(rem, dividend, divisor);
  22. }
  23. /* This function returns a new context for Barrett based operations on
  24. * the modulus M. This context needs to be released using
  25. * _gcry_mpi_barrett_free. If COPY is true M will be transferred to
  26. * the context and the user may change M. If COPY is false, M may not
  27. * be changed until gcry_mpi_barrett_free has been called.
  28. */
  29. mpi_barrett_t mpi_barrett_init(MPI m, int copy)
  30. {
  31. mpi_barrett_t ctx;
  32. MPI tmp;
  33. mpi_normalize(m);
  34. ctx = kcalloc(1, sizeof(*ctx), GFP_KERNEL);
  35. if (!ctx)
  36. return NULL;
  37. if (copy) {
  38. ctx->m = mpi_copy(m);
  39. ctx->m_copied = 1;
  40. } else
  41. ctx->m = m;
  42. ctx->k = mpi_get_nlimbs(m);
  43. tmp = mpi_alloc(ctx->k + 1);
  44. /* Barrett precalculation: y = floor(b^(2k) / m). */
  45. mpi_set_ui(tmp, 1);
  46. mpi_lshift_limbs(tmp, 2 * ctx->k);
  47. mpi_fdiv_q(tmp, tmp, m);
  48. ctx->y = tmp;
  49. ctx->r1 = mpi_alloc(2 * ctx->k + 1);
  50. ctx->r2 = mpi_alloc(2 * ctx->k + 1);
  51. return ctx;
  52. }
  53. void mpi_barrett_free(mpi_barrett_t ctx)
  54. {
  55. if (ctx) {
  56. mpi_free(ctx->y);
  57. mpi_free(ctx->r1);
  58. mpi_free(ctx->r2);
  59. if (ctx->r3)
  60. mpi_free(ctx->r3);
  61. if (ctx->m_copied)
  62. mpi_free(ctx->m);
  63. kfree(ctx);
  64. }
  65. }
  66. /* R = X mod M
  67. *
  68. * Using Barrett reduction. Before using this function
  69. * _gcry_mpi_barrett_init must have been called to do the
  70. * precalculations. CTX is the context created by this precalculation
  71. * and also conveys M. If the Barret reduction could no be done a
  72. * straightforward reduction method is used.
  73. *
  74. * We assume that these conditions are met:
  75. * Input: x =(x_2k-1 ...x_0)_b
  76. * m =(m_k-1 ....m_0)_b with m_k-1 != 0
  77. * Output: r = x mod m
  78. */
  79. void mpi_mod_barrett(MPI r, MPI x, mpi_barrett_t ctx)
  80. {
  81. MPI m = ctx->m;
  82. int k = ctx->k;
  83. MPI y = ctx->y;
  84. MPI r1 = ctx->r1;
  85. MPI r2 = ctx->r2;
  86. int sign;
  87. mpi_normalize(x);
  88. if (mpi_get_nlimbs(x) > 2*k) {
  89. mpi_mod(r, x, m);
  90. return;
  91. }
  92. sign = x->sign;
  93. x->sign = 0;
  94. /* 1. q1 = floor( x / b^k-1)
  95. * q2 = q1 * y
  96. * q3 = floor( q2 / b^k+1 )
  97. * Actually, we don't need qx, we can work direct on r2
  98. */
  99. mpi_set(r2, x);
  100. mpi_rshift_limbs(r2, k-1);
  101. mpi_mul(r2, r2, y);
  102. mpi_rshift_limbs(r2, k+1);
  103. /* 2. r1 = x mod b^k+1
  104. * r2 = q3 * m mod b^k+1
  105. * r = r1 - r2
  106. * 3. if r < 0 then r = r + b^k+1
  107. */
  108. mpi_set(r1, x);
  109. if (r1->nlimbs > k+1) /* Quick modulo operation. */
  110. r1->nlimbs = k+1;
  111. mpi_mul(r2, r2, m);
  112. if (r2->nlimbs > k+1) /* Quick modulo operation. */
  113. r2->nlimbs = k+1;
  114. mpi_sub(r, r1, r2);
  115. if (mpi_has_sign(r)) {
  116. if (!ctx->r3) {
  117. ctx->r3 = mpi_alloc(k + 2);
  118. mpi_set_ui(ctx->r3, 1);
  119. mpi_lshift_limbs(ctx->r3, k + 1);
  120. }
  121. mpi_add(r, r, ctx->r3);
  122. }
  123. /* 4. while r >= m do r = r - m */
  124. while (mpi_cmp(r, m) >= 0)
  125. mpi_sub(r, r, m);
  126. x->sign = sign;
  127. }
  128. void mpi_mul_barrett(MPI w, MPI u, MPI v, mpi_barrett_t ctx)
  129. {
  130. mpi_mul(w, u, v);
  131. mpi_mod_barrett(w, w, ctx);
  132. }