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