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