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
mpi_mul(MPI w,MPI u,MPI v)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
mpi_mulm(MPI w,MPI u,MPI v,MPI m)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