1 /* mpi-add.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_add(MPI w,MPI u,MPI v)18 int mpi_add(MPI w, MPI u, MPI v)
19 {
20 mpi_ptr_t wp, up, vp;
21 mpi_size_t usize, vsize, wsize;
22 int usign, vsign, wsign;
23 int err;
24
25 if (u->nlimbs < v->nlimbs) { /* Swap U and V. */
26 usize = v->nlimbs;
27 usign = v->sign;
28 vsize = u->nlimbs;
29 vsign = u->sign;
30 wsize = usize + 1;
31 err = RESIZE_IF_NEEDED(w, wsize);
32 if (err)
33 return err;
34 /* These must be after realloc (u or v may be the same as w). */
35 up = v->d;
36 vp = u->d;
37 } else {
38 usize = u->nlimbs;
39 usign = u->sign;
40 vsize = v->nlimbs;
41 vsign = v->sign;
42 wsize = usize + 1;
43 err = RESIZE_IF_NEEDED(w, wsize);
44 if (err)
45 return err;
46 /* These must be after realloc (u or v may be the same as w). */
47 up = u->d;
48 vp = v->d;
49 }
50 wp = w->d;
51 wsign = 0;
52
53 if (!vsize) { /* simple */
54 MPN_COPY(wp, up, usize);
55 wsize = usize;
56 wsign = usign;
57 } else if (usign != vsign) { /* different sign */
58 /* This test is right since USIZE >= VSIZE */
59 if (usize != vsize) {
60 mpihelp_sub(wp, up, usize, vp, vsize);
61 wsize = usize;
62 MPN_NORMALIZE(wp, wsize);
63 wsign = usign;
64 } else if (mpihelp_cmp(up, vp, usize) < 0) {
65 mpihelp_sub_n(wp, vp, up, usize);
66 wsize = usize;
67 MPN_NORMALIZE(wp, wsize);
68 if (!usign)
69 wsign = 1;
70 } else {
71 mpihelp_sub_n(wp, up, vp, usize);
72 wsize = usize;
73 MPN_NORMALIZE(wp, wsize);
74 if (usign)
75 wsign = 1;
76 }
77 } else { /* U and V have same sign. Add them. */
78 mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
79 wp[usize] = cy;
80 wsize = usize + cy;
81 if (usign)
82 wsign = 1;
83 }
84
85 w->nlimbs = wsize;
86 w->sign = wsign;
87 return 0;
88 }
89 EXPORT_SYMBOL_GPL(mpi_add);
90
mpi_sub(MPI w,MPI u,MPI v)91 int mpi_sub(MPI w, MPI u, MPI v)
92 {
93 int err;
94 MPI vv;
95
96 vv = mpi_copy(v);
97 if (!vv)
98 return -ENOMEM;
99
100 vv->sign = !vv->sign;
101 err = mpi_add(w, u, vv);
102 mpi_free(vv);
103
104 return err;
105 }
106 EXPORT_SYMBOL_GPL(mpi_sub);
107
mpi_addm(MPI w,MPI u,MPI v,MPI m)108 int mpi_addm(MPI w, MPI u, MPI v, MPI m)
109 {
110 return mpi_add(w, u, v) ?:
111 mpi_mod(w, w, m);
112 }
113 EXPORT_SYMBOL_GPL(mpi_addm);
114
mpi_subm(MPI w,MPI u,MPI v,MPI m)115 int mpi_subm(MPI w, MPI u, MPI v, MPI m)
116 {
117 return mpi_sub(w, u, v) ?:
118 mpi_mod(w, w, m);
119 }
120 EXPORT_SYMBOL_GPL(mpi_subm);
121