1*2a598d0bSHerbert Xu /* mpi-add.c - MPI functions
2*2a598d0bSHerbert Xu * Copyright (C) 1994, 1996, 1998, 2001, 2002,
3*2a598d0bSHerbert Xu * 2003 Free Software Foundation, Inc.
4*2a598d0bSHerbert Xu *
5*2a598d0bSHerbert Xu * This file is part of Libgcrypt.
6*2a598d0bSHerbert Xu *
7*2a598d0bSHerbert Xu * Note: This code is heavily based on the GNU MP Library.
8*2a598d0bSHerbert Xu * Actually it's the same code with only minor changes in the
9*2a598d0bSHerbert Xu * way the data is stored; this is to support the abstraction
10*2a598d0bSHerbert Xu * of an optional secure memory allocation which may be used
11*2a598d0bSHerbert Xu * to avoid revealing of sensitive data due to paging etc.
12*2a598d0bSHerbert Xu */
13*2a598d0bSHerbert Xu
14*2a598d0bSHerbert Xu #include "mpi-internal.h"
15*2a598d0bSHerbert Xu
16*2a598d0bSHerbert Xu /****************
17*2a598d0bSHerbert Xu * Add the unsigned integer V to the mpi-integer U and store the
18*2a598d0bSHerbert Xu * result in W. U and V may be the same.
19*2a598d0bSHerbert Xu */
mpi_add_ui(MPI w,MPI u,unsigned long v)20*2a598d0bSHerbert Xu void mpi_add_ui(MPI w, MPI u, unsigned long v)
21*2a598d0bSHerbert Xu {
22*2a598d0bSHerbert Xu mpi_ptr_t wp, up;
23*2a598d0bSHerbert Xu mpi_size_t usize, wsize;
24*2a598d0bSHerbert Xu int usign, wsign;
25*2a598d0bSHerbert Xu
26*2a598d0bSHerbert Xu usize = u->nlimbs;
27*2a598d0bSHerbert Xu usign = u->sign;
28*2a598d0bSHerbert Xu wsign = 0;
29*2a598d0bSHerbert Xu
30*2a598d0bSHerbert Xu /* If not space for W (and possible carry), increase space. */
31*2a598d0bSHerbert Xu wsize = usize + 1;
32*2a598d0bSHerbert Xu if (w->alloced < wsize)
33*2a598d0bSHerbert Xu mpi_resize(w, wsize);
34*2a598d0bSHerbert Xu
35*2a598d0bSHerbert Xu /* These must be after realloc (U may be the same as W). */
36*2a598d0bSHerbert Xu up = u->d;
37*2a598d0bSHerbert Xu wp = w->d;
38*2a598d0bSHerbert Xu
39*2a598d0bSHerbert Xu if (!usize) { /* simple */
40*2a598d0bSHerbert Xu wp[0] = v;
41*2a598d0bSHerbert Xu wsize = v ? 1:0;
42*2a598d0bSHerbert Xu } else if (!usign) { /* mpi is not negative */
43*2a598d0bSHerbert Xu mpi_limb_t cy;
44*2a598d0bSHerbert Xu cy = mpihelp_add_1(wp, up, usize, v);
45*2a598d0bSHerbert Xu wp[usize] = cy;
46*2a598d0bSHerbert Xu wsize = usize + cy;
47*2a598d0bSHerbert Xu } else {
48*2a598d0bSHerbert Xu /* The signs are different. Need exact comparison to determine
49*2a598d0bSHerbert Xu * which operand to subtract from which.
50*2a598d0bSHerbert Xu */
51*2a598d0bSHerbert Xu if (usize == 1 && up[0] < v) {
52*2a598d0bSHerbert Xu wp[0] = v - up[0];
53*2a598d0bSHerbert Xu wsize = 1;
54*2a598d0bSHerbert Xu } else {
55*2a598d0bSHerbert Xu mpihelp_sub_1(wp, up, usize, v);
56*2a598d0bSHerbert Xu /* Size can decrease with at most one limb. */
57*2a598d0bSHerbert Xu wsize = usize - (wp[usize-1] == 0);
58*2a598d0bSHerbert Xu wsign = 1;
59*2a598d0bSHerbert Xu }
60*2a598d0bSHerbert Xu }
61*2a598d0bSHerbert Xu
62*2a598d0bSHerbert Xu w->nlimbs = wsize;
63*2a598d0bSHerbert Xu w->sign = wsign;
64*2a598d0bSHerbert Xu }
65*2a598d0bSHerbert Xu
66*2a598d0bSHerbert Xu
mpi_add(MPI w,MPI u,MPI v)67*2a598d0bSHerbert Xu void mpi_add(MPI w, MPI u, MPI v)
68*2a598d0bSHerbert Xu {
69*2a598d0bSHerbert Xu mpi_ptr_t wp, up, vp;
70*2a598d0bSHerbert Xu mpi_size_t usize, vsize, wsize;
71*2a598d0bSHerbert Xu int usign, vsign, wsign;
72*2a598d0bSHerbert Xu
73*2a598d0bSHerbert Xu if (u->nlimbs < v->nlimbs) { /* Swap U and V. */
74*2a598d0bSHerbert Xu usize = v->nlimbs;
75*2a598d0bSHerbert Xu usign = v->sign;
76*2a598d0bSHerbert Xu vsize = u->nlimbs;
77*2a598d0bSHerbert Xu vsign = u->sign;
78*2a598d0bSHerbert Xu wsize = usize + 1;
79*2a598d0bSHerbert Xu RESIZE_IF_NEEDED(w, wsize);
80*2a598d0bSHerbert Xu /* These must be after realloc (u or v may be the same as w). */
81*2a598d0bSHerbert Xu up = v->d;
82*2a598d0bSHerbert Xu vp = u->d;
83*2a598d0bSHerbert Xu } else {
84*2a598d0bSHerbert Xu usize = u->nlimbs;
85*2a598d0bSHerbert Xu usign = u->sign;
86*2a598d0bSHerbert Xu vsize = v->nlimbs;
87*2a598d0bSHerbert Xu vsign = v->sign;
88*2a598d0bSHerbert Xu wsize = usize + 1;
89*2a598d0bSHerbert Xu RESIZE_IF_NEEDED(w, wsize);
90*2a598d0bSHerbert Xu /* These must be after realloc (u or v may be the same as w). */
91*2a598d0bSHerbert Xu up = u->d;
92*2a598d0bSHerbert Xu vp = v->d;
93*2a598d0bSHerbert Xu }
94*2a598d0bSHerbert Xu wp = w->d;
95*2a598d0bSHerbert Xu wsign = 0;
96*2a598d0bSHerbert Xu
97*2a598d0bSHerbert Xu if (!vsize) { /* simple */
98*2a598d0bSHerbert Xu MPN_COPY(wp, up, usize);
99*2a598d0bSHerbert Xu wsize = usize;
100*2a598d0bSHerbert Xu wsign = usign;
101*2a598d0bSHerbert Xu } else if (usign != vsign) { /* different sign */
102*2a598d0bSHerbert Xu /* This test is right since USIZE >= VSIZE */
103*2a598d0bSHerbert Xu if (usize != vsize) {
104*2a598d0bSHerbert Xu mpihelp_sub(wp, up, usize, vp, vsize);
105*2a598d0bSHerbert Xu wsize = usize;
106*2a598d0bSHerbert Xu MPN_NORMALIZE(wp, wsize);
107*2a598d0bSHerbert Xu wsign = usign;
108*2a598d0bSHerbert Xu } else if (mpihelp_cmp(up, vp, usize) < 0) {
109*2a598d0bSHerbert Xu mpihelp_sub_n(wp, vp, up, usize);
110*2a598d0bSHerbert Xu wsize = usize;
111*2a598d0bSHerbert Xu MPN_NORMALIZE(wp, wsize);
112*2a598d0bSHerbert Xu if (!usign)
113*2a598d0bSHerbert Xu wsign = 1;
114*2a598d0bSHerbert Xu } else {
115*2a598d0bSHerbert Xu mpihelp_sub_n(wp, up, vp, usize);
116*2a598d0bSHerbert Xu wsize = usize;
117*2a598d0bSHerbert Xu MPN_NORMALIZE(wp, wsize);
118*2a598d0bSHerbert Xu if (usign)
119*2a598d0bSHerbert Xu wsign = 1;
120*2a598d0bSHerbert Xu }
121*2a598d0bSHerbert Xu } else { /* U and V have same sign. Add them. */
122*2a598d0bSHerbert Xu mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
123*2a598d0bSHerbert Xu wp[usize] = cy;
124*2a598d0bSHerbert Xu wsize = usize + cy;
125*2a598d0bSHerbert Xu if (usign)
126*2a598d0bSHerbert Xu wsign = 1;
127*2a598d0bSHerbert Xu }
128*2a598d0bSHerbert Xu
129*2a598d0bSHerbert Xu w->nlimbs = wsize;
130*2a598d0bSHerbert Xu w->sign = wsign;
131*2a598d0bSHerbert Xu }
132*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_add);
133*2a598d0bSHerbert Xu
mpi_sub(MPI w,MPI u,MPI v)134*2a598d0bSHerbert Xu void mpi_sub(MPI w, MPI u, MPI v)
135*2a598d0bSHerbert Xu {
136*2a598d0bSHerbert Xu MPI vv = mpi_copy(v);
137*2a598d0bSHerbert Xu vv->sign = !vv->sign;
138*2a598d0bSHerbert Xu mpi_add(w, u, vv);
139*2a598d0bSHerbert Xu mpi_free(vv);
140*2a598d0bSHerbert Xu }
141*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_sub);
142*2a598d0bSHerbert Xu
mpi_addm(MPI w,MPI u,MPI v,MPI m)143*2a598d0bSHerbert Xu void mpi_addm(MPI w, MPI u, MPI v, MPI m)
144*2a598d0bSHerbert Xu {
145*2a598d0bSHerbert Xu mpi_add(w, u, v);
146*2a598d0bSHerbert Xu mpi_mod(w, w, m);
147*2a598d0bSHerbert Xu }
148*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_addm);
149*2a598d0bSHerbert Xu
mpi_subm(MPI w,MPI u,MPI v,MPI m)150*2a598d0bSHerbert Xu void mpi_subm(MPI w, MPI u, MPI v, MPI m)
151*2a598d0bSHerbert Xu {
152*2a598d0bSHerbert Xu mpi_sub(w, u, v);
153*2a598d0bSHerbert Xu mpi_mod(w, w, m);
154*2a598d0bSHerbert Xu }
155*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_subm);
156