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 14 #include "mpi-internal.h" 15 16 void mpi_mul(MPI w, MPI u, MPI v) 17 { 18 mpi_size_t usize, vsize, wsize; 19 mpi_ptr_t up, vp, wp; 20 mpi_limb_t cy; 21 int usign, vsign, sign_product; 22 int assign_wp = 0; 23 mpi_ptr_t tmp_limb = NULL; 24 25 if (u->nlimbs < v->nlimbs) { 26 /* Swap U and V. */ 27 usize = v->nlimbs; 28 usign = v->sign; 29 up = v->d; 30 vsize = u->nlimbs; 31 vsign = u->sign; 32 vp = u->d; 33 } else { 34 usize = u->nlimbs; 35 usign = u->sign; 36 up = u->d; 37 vsize = v->nlimbs; 38 vsign = v->sign; 39 vp = v->d; 40 } 41 sign_product = usign ^ vsign; 42 wp = w->d; 43 44 /* Ensure W has space enough to store the result. */ 45 wsize = usize + vsize; 46 if (w->alloced < wsize) { 47 if (wp == up || wp == vp) { 48 wp = mpi_alloc_limb_space(wsize); 49 assign_wp = 1; 50 } else { 51 mpi_resize(w, wsize); 52 wp = w->d; 53 } 54 } else { /* Make U and V not overlap with W. */ 55 if (wp == up) { 56 /* W and U are identical. Allocate temporary space for U. */ 57 up = tmp_limb = mpi_alloc_limb_space(usize); 58 /* Is V identical too? Keep it identical with U. */ 59 if (wp == vp) 60 vp = up; 61 /* Copy to the temporary space. */ 62 MPN_COPY(up, wp, usize); 63 } else if (wp == vp) { 64 /* W and V are identical. Allocate temporary space for V. */ 65 vp = tmp_limb = mpi_alloc_limb_space(vsize); 66 /* Copy to the temporary space. */ 67 MPN_COPY(vp, wp, vsize); 68 } 69 } 70 71 if (!vsize) 72 wsize = 0; 73 else { 74 mpihelp_mul(wp, up, usize, vp, vsize, &cy); 75 wsize -= cy ? 0:1; 76 } 77 78 if (assign_wp) 79 mpi_assign_limb_space(w, wp, wsize); 80 w->nlimbs = wsize; 81 w->sign = sign_product; 82 if (tmp_limb) 83 mpi_free_limb_space(tmp_limb); 84 } 85 EXPORT_SYMBOL_GPL(mpi_mul); 86 87 void mpi_mulm(MPI w, MPI u, MPI v, MPI m) 88 { 89 mpi_mul(w, u, v); 90 mpi_tdiv_r(w, w, m); 91 } 92 EXPORT_SYMBOL_GPL(mpi_mulm); 93