mpi-add.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* mpi-add.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 <linux/export.h>
  14. #include "mpi-internal.h"
  15. int mpi_add(MPI w, MPI u, MPI v)
  16. {
  17. mpi_ptr_t wp, up, vp;
  18. mpi_size_t usize, vsize, wsize;
  19. int usign, vsign, wsign;
  20. int err;
  21. if (u->nlimbs < v->nlimbs) { /* Swap U and V. */
  22. usize = v->nlimbs;
  23. usign = v->sign;
  24. vsize = u->nlimbs;
  25. vsign = u->sign;
  26. wsize = usize + 1;
  27. err = RESIZE_IF_NEEDED(w, wsize);
  28. if (err)
  29. return err;
  30. /* These must be after realloc (u or v may be the same as w). */
  31. up = v->d;
  32. vp = u->d;
  33. } else {
  34. usize = u->nlimbs;
  35. usign = u->sign;
  36. vsize = v->nlimbs;
  37. vsign = v->sign;
  38. wsize = usize + 1;
  39. err = RESIZE_IF_NEEDED(w, wsize);
  40. if (err)
  41. return err;
  42. /* These must be after realloc (u or v may be the same as w). */
  43. up = u->d;
  44. vp = v->d;
  45. }
  46. wp = w->d;
  47. wsign = 0;
  48. if (!vsize) { /* simple */
  49. MPN_COPY(wp, up, usize);
  50. wsize = usize;
  51. wsign = usign;
  52. } else if (usign != vsign) { /* different sign */
  53. /* This test is right since USIZE >= VSIZE */
  54. if (usize != vsize) {
  55. mpihelp_sub(wp, up, usize, vp, vsize);
  56. wsize = usize;
  57. MPN_NORMALIZE(wp, wsize);
  58. wsign = usign;
  59. } else if (mpihelp_cmp(up, vp, usize) < 0) {
  60. mpihelp_sub_n(wp, vp, up, usize);
  61. wsize = usize;
  62. MPN_NORMALIZE(wp, wsize);
  63. if (!usign)
  64. wsign = 1;
  65. } else {
  66. mpihelp_sub_n(wp, up, vp, usize);
  67. wsize = usize;
  68. MPN_NORMALIZE(wp, wsize);
  69. if (usign)
  70. wsign = 1;
  71. }
  72. } else { /* U and V have same sign. Add them. */
  73. mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
  74. wp[usize] = cy;
  75. wsize = usize + cy;
  76. if (usign)
  77. wsign = 1;
  78. }
  79. w->nlimbs = wsize;
  80. w->sign = wsign;
  81. return 0;
  82. }
  83. EXPORT_SYMBOL_GPL(mpi_add);
  84. int mpi_sub(MPI w, MPI u, MPI v)
  85. {
  86. int err;
  87. MPI vv;
  88. vv = mpi_copy(v);
  89. if (!vv)
  90. return -ENOMEM;
  91. vv->sign = !vv->sign;
  92. err = mpi_add(w, u, vv);
  93. mpi_free(vv);
  94. return err;
  95. }
  96. EXPORT_SYMBOL_GPL(mpi_sub);
  97. int mpi_addm(MPI w, MPI u, MPI v, MPI m)
  98. {
  99. return mpi_add(w, u, v) ?:
  100. mpi_mod(w, w, m);
  101. }
  102. EXPORT_SYMBOL_GPL(mpi_addm);
  103. int mpi_subm(MPI w, MPI u, MPI v, MPI m)
  104. {
  105. return mpi_sub(w, u, v) ?:
  106. mpi_mod(w, w, m);
  107. }
  108. EXPORT_SYMBOL_GPL(mpi_subm);