1 /* mpi-mul.c - MPI functions
2 * Copyright (C) 1994, 1996 Free Software Foundation, Inc.
3 * Copyright (C) 1998, 2001 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 * Note: This code is heavily based on the GNU MP Library.
22 * Actually it's the same code with only minor changes in the
23 * way the data is stored; this is to support the abstraction
24 * of an optional secure memory allocation which may be used
25 * to avoid revealing of sensitive data due to paging etc.
26 * The GNU MP Library itself is published under the LGPL;
27 * however I decided to publish this code under the plain GPL.
30 #include "mpi-internal.h"
32 int mpi_mul_ui(MPI prod, MPI mult, unsigned long small_mult)
34 mpi_size_t size, prod_size;
42 if (!size || !small_mult) {
49 if (prod->alloced < prod_size)
50 if (mpi_resize(prod, prod_size) < 0)
54 cy = mpihelp_mul_1(prod_ptr, mult->d, size, (mpi_limb_t) small_mult);
56 prod_ptr[size++] = cy;
62 int mpi_mul_2exp(MPI w, MPI u, unsigned long cnt)
64 mpi_size_t usize, wsize, limb_cnt;
78 limb_cnt = cnt / BITS_PER_MPI_LIMB;
79 wsize = usize + limb_cnt + 1;
80 if (w->alloced < wsize)
81 if (mpi_resize(w, wsize) < 0)
84 wsize = usize + limb_cnt;
87 cnt %= BITS_PER_MPI_LIMB;
89 wlimb = mpihelp_lshift(wp + limb_cnt, u->d, usize, cnt);
95 MPN_COPY_DECR(wp + limb_cnt, u->d, usize);
98 /* Zero all whole limbs at low end. Do it here and not before calling
99 * mpn_lshift, not to lose for U == W. */
100 MPN_ZERO(wp, limb_cnt);
107 int mpi_mul(MPI w, MPI u, MPI v)
110 mpi_size_t usize, vsize, wsize;
111 mpi_ptr_t up, vp, wp;
113 int usign, vsign, sign_product;
115 mpi_ptr_t tmp_limb = NULL;
117 if (u->nlimbs < v->nlimbs) { /* Swap U and V. */
132 sign_product = usign ^ vsign;
135 /* Ensure W has space enough to store the result. */
136 wsize = usize + vsize;
137 if (w->alloced < (size_t) wsize) {
138 if (wp == up || wp == vp) {
139 wp = mpi_alloc_limb_space(wsize);
144 if (mpi_resize(w, wsize) < 0)
148 } else { /* Make U and V not overlap with W. */
150 /* W and U are identical. Allocate temporary space for U. */
151 up = tmp_limb = mpi_alloc_limb_space(usize);
154 /* Is V identical too? Keep it identical with U. */
157 /* Copy to the temporary space. */
158 MPN_COPY(up, wp, usize);
159 } else if (wp == vp) {
160 /* W and V are identical. Allocate temporary space for V. */
161 vp = tmp_limb = mpi_alloc_limb_space(vsize);
164 /* Copy to the temporary space. */
165 MPN_COPY(vp, wp, vsize);
172 if (mpihelp_mul(wp, up, usize, vp, vsize, &cy) < 0)
178 mpi_assign_limb_space(w, wp, wsize);
181 w->sign = sign_product;
185 mpi_free_limb_space(tmp_limb);
189 int mpi_mulm(MPI w, MPI u, MPI v, MPI m)
191 if (mpi_mul(w, u, v) < 0)
193 return mpi_fdiv_r(w, w, m);