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"
34 mpi_mul_ui( MPI prod, MPI mult, unsigned long small_mult )
36 mpi_size_t size, prod_size;
44 if( !size || !small_mult ) {
51 if( prod->alloced < prod_size )
52 if (mpi_resize( prod, prod_size ) < 0)
56 cy = mpihelp_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult );
58 prod_ptr[size++] = cy;
66 mpi_mul_2exp( MPI w, MPI u, unsigned long cnt)
68 mpi_size_t usize, wsize, limb_cnt;
82 limb_cnt = cnt / BITS_PER_MPI_LIMB;
83 wsize = usize + limb_cnt + 1;
84 if( w->alloced < wsize )
85 if (mpi_resize(w, wsize ) < 0)
88 wsize = usize + limb_cnt;
91 cnt %= BITS_PER_MPI_LIMB;
93 wlimb = mpihelp_lshift( wp + limb_cnt, u->d, usize, cnt );
100 MPN_COPY_DECR( wp + limb_cnt, u->d, usize );
103 /* Zero all whole limbs at low end. Do it here and not before calling
104 * mpn_lshift, not to lose for U == W. */
105 MPN_ZERO( wp, limb_cnt );
113 mpi_mul( MPI w, MPI u, MPI v)
116 mpi_size_t usize, vsize, wsize;
117 mpi_ptr_t up, vp, wp;
119 int usign, vsign, sign_product;
121 mpi_ptr_t tmp_limb=NULL;
124 if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
140 sign_product = usign ^ vsign;
143 /* Ensure W has space enough to store the result. */
144 wsize = usize + vsize;
145 if( w->alloced < (size_t)wsize ) {
146 if( wp == up || wp == vp ) {
147 wp = mpi_alloc_limb_space(wsize);
152 if (mpi_resize(w, wsize ) < 0) goto nomem;
156 else { /* Make U and V not overlap with W. */
158 /* W and U are identical. Allocate temporary space for U. */
159 up = tmp_limb = mpi_alloc_limb_space( usize);
161 /* Is V identical too? Keep it identical with U. */
164 /* Copy to the temporary space. */
165 MPN_COPY( up, wp, usize );
167 else if( wp == vp ) {
168 /* W and V are identical. Allocate temporary space for V. */
169 vp = tmp_limb = mpi_alloc_limb_space( vsize);
171 /* Copy to the temporary space. */
172 MPN_COPY( vp, wp, vsize );
179 if (mpihelp_mul( wp, up, usize, vp, vsize, &cy) < 0)
185 mpi_assign_limb_space( w, wp, wsize );
188 w->sign = sign_product;
192 mpi_free_limb_space( tmp_limb );
197 mpi_mulm( MPI w, MPI u, MPI v, MPI m)
199 if (mpi_mul(w, u, v) < 0)
201 return mpi_fdiv_r( w, w, m );