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
);