xref: /openbmc/linux/lib/crypto/mpi/mpi-add.c (revision 2a598d0b)
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