mpi-mul.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /* mpi-mul.c - MPI functions
  2. * Copyright (C) 1994, 1996, 1998, 2001, 2002,
  3. * 2003 Free Software Foundation, Inc.
  4. *
  5. * This file is part of Libgcrypt.
  6. *
  7. * Note: This code is heavily based on the GNU MP Library.
  8. * Actually it's the same code with only minor changes in the
  9. * way the data is stored; this is to support the abstraction
  10. * of an optional secure memory allocation which may be used
  11. * to avoid revealing of sensitive data due to paging etc.
  12. */
  13. #include "mpi-internal.h"
  14. void mpi_mul(MPI w, MPI u, MPI v)
  15. {
  16. mpi_size_t usize, vsize, wsize;
  17. mpi_ptr_t up, vp, wp;
  18. mpi_limb_t cy;
  19. int usign, vsign, sign_product;
  20. int assign_wp = 0;
  21. mpi_ptr_t tmp_limb = NULL;
  22. if (u->nlimbs < v->nlimbs) {
  23. /* Swap U and V. */
  24. usize = v->nlimbs;
  25. usign = v->sign;
  26. up = v->d;
  27. vsize = u->nlimbs;
  28. vsign = u->sign;
  29. vp = u->d;
  30. } else {
  31. usize = u->nlimbs;
  32. usign = u->sign;
  33. up = u->d;
  34. vsize = v->nlimbs;
  35. vsign = v->sign;
  36. vp = v->d;
  37. }
  38. sign_product = usign ^ vsign;
  39. wp = w->d;
  40. /* Ensure W has space enough to store the result. */
  41. wsize = usize + vsize;
  42. if (w->alloced < wsize) {
  43. if (wp == up || wp == vp) {
  44. wp = mpi_alloc_limb_space(wsize);
  45. assign_wp = 1;
  46. } else {
  47. mpi_resize(w, wsize);
  48. wp = w->d;
  49. }
  50. } else { /* Make U and V not overlap with W. */
  51. if (wp == up) {
  52. /* W and U are identical. Allocate temporary space for U. */
  53. up = tmp_limb = mpi_alloc_limb_space(usize);
  54. /* Is V identical too? Keep it identical with U. */
  55. if (wp == vp)
  56. vp = up;
  57. /* Copy to the temporary space. */
  58. MPN_COPY(up, wp, usize);
  59. } else if (wp == vp) {
  60. /* W and V are identical. Allocate temporary space for V. */
  61. vp = tmp_limb = mpi_alloc_limb_space(vsize);
  62. /* Copy to the temporary space. */
  63. MPN_COPY(vp, wp, vsize);
  64. }
  65. }
  66. if (!vsize)
  67. wsize = 0;
  68. else {
  69. mpihelp_mul(wp, up, usize, vp, vsize, &cy);
  70. wsize -= cy ? 0:1;
  71. }
  72. if (assign_wp)
  73. mpi_assign_limb_space(w, wp, wsize);
  74. w->nlimbs = wsize;
  75. w->sign = sign_product;
  76. if (tmp_limb)
  77. mpi_free_limb_space(tmp_limb);
  78. }
  79. void mpi_mulm(MPI w, MPI u, MPI v, MPI m)
  80. {
  81. mpi_mul(w, u, v);
  82. mpi_tdiv_r(w, w, m);
  83. }
  84. EXPORT_SYMBOL_GPL(mpi_mulm);