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 int 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 int err = 0; 25 26 if (u->nlimbs < v->nlimbs) { 27 /* Swap U and V. */ 28 usize = v->nlimbs; 29 usign = v->sign; 30 up = v->d; 31 vsize = u->nlimbs; 32 vsign = u->sign; 33 vp = u->d; 34 } else { 35 usize = u->nlimbs; 36 usign = u->sign; 37 up = u->d; 38 vsize = v->nlimbs; 39 vsign = v->sign; 40 vp = v->d; 41 } 42 sign_product = usign ^ vsign; 43 wp = w->d; 44 45 /* Ensure W has space enough to store the result. */ 46 wsize = usize + vsize; 47 if (w->alloced < wsize) { 48 if (wp == up || wp == vp) { 49 wp = mpi_alloc_limb_space(wsize); 50 if (!wp) 51 return -ENOMEM; 52 assign_wp = 1; 53 } else { 54 err = mpi_resize(w, wsize); 55 if (err) 56 return err; 57 wp = w->d; 58 } 59 } else { /* Make U and V not overlap with W. */ 60 if (wp == up) { 61 /* W and U are identical. Allocate temporary space for U. */ 62 up = tmp_limb = mpi_alloc_limb_space(usize); 63 if (!up) 64 return -ENOMEM; 65 /* Is V identical too? Keep it identical with U. */ 66 if (wp == vp) 67 vp = up; 68 /* Copy to the temporary space. */ 69 MPN_COPY(up, wp, usize); 70 } else if (wp == vp) { 71 /* W and V are identical. Allocate temporary space for V. */ 72 vp = tmp_limb = mpi_alloc_limb_space(vsize); 73 if (!vp) 74 return -ENOMEM; 75 /* Copy to the temporary space. */ 76 MPN_COPY(vp, wp, vsize); 77 } 78 } 79 80 if (!vsize) 81 wsize = 0; 82 else { 83 err = mpihelp_mul(wp, up, usize, vp, vsize, &cy); 84 if (err) { 85 if (assign_wp) 86 mpi_free_limb_space(wp); 87 goto free_tmp_limb; 88 } 89 wsize -= cy ? 0:1; 90 } 91 92 if (assign_wp) 93 mpi_assign_limb_space(w, wp, wsize); 94 w->nlimbs = wsize; 95 w->sign = sign_product; 96 97 free_tmp_limb: 98 if (tmp_limb) 99 mpi_free_limb_space(tmp_limb); 100 return err; 101 } 102 EXPORT_SYMBOL_GPL(mpi_mul); 103 104 int mpi_mulm(MPI w, MPI u, MPI v, MPI m) 105 { 106 return mpi_mul(w, u, v) ?: 107 mpi_tdiv_r(w, w, m); 108 } 109 EXPORT_SYMBOL_GPL(mpi_mulm); 110