• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "mpi-internal.h"
15  
16  /****************
17   * Add the unsigned integer V to the mpi-integer U and store the
18   * result in W. U and V may be the same.
19   */
mpi_add_ui(MPI w,MPI u,unsigned long v)20  void mpi_add_ui(MPI w, MPI u, unsigned long v)
21  {
22  	mpi_ptr_t wp, up;
23  	mpi_size_t usize, wsize;
24  	int usign, wsign;
25  
26  	usize = u->nlimbs;
27  	usign = u->sign;
28  	wsign = 0;
29  
30  	/* If not space for W (and possible carry), increase space.  */
31  	wsize = usize + 1;
32  	if (w->alloced < wsize)
33  		mpi_resize(w, wsize);
34  
35  	/* These must be after realloc (U may be the same as W).  */
36  	up = u->d;
37  	wp = w->d;
38  
39  	if (!usize) {  /* simple */
40  		wp[0] = v;
41  		wsize = v ? 1:0;
42  	} else if (!usign) {  /* mpi is not negative */
43  		mpi_limb_t cy;
44  		cy = mpihelp_add_1(wp, up, usize, v);
45  		wp[usize] = cy;
46  		wsize = usize + cy;
47  	} else {
48  		/* The signs are different.  Need exact comparison to determine
49  		 * which operand to subtract from which.
50  		 */
51  		if (usize == 1 && up[0] < v) {
52  			wp[0] = v - up[0];
53  			wsize = 1;
54  		} else {
55  			mpihelp_sub_1(wp, up, usize, v);
56  			/* Size can decrease with at most one limb. */
57  			wsize = usize - (wp[usize-1] == 0);
58  			wsign = 1;
59  		}
60  	}
61  
62  	w->nlimbs = wsize;
63  	w->sign   = wsign;
64  }
65  
66  
mpi_add(MPI w,MPI u,MPI v)67  void mpi_add(MPI w, MPI u, MPI v)
68  {
69  	mpi_ptr_t wp, up, vp;
70  	mpi_size_t usize, vsize, wsize;
71  	int usign, vsign, wsign;
72  
73  	if (u->nlimbs < v->nlimbs) { /* Swap U and V. */
74  		usize = v->nlimbs;
75  		usign = v->sign;
76  		vsize = u->nlimbs;
77  		vsign = u->sign;
78  		wsize = usize + 1;
79  		RESIZE_IF_NEEDED(w, wsize);
80  		/* These must be after realloc (u or v may be the same as w).  */
81  		up = v->d;
82  		vp = u->d;
83  	} else {
84  		usize = u->nlimbs;
85  		usign = u->sign;
86  		vsize = v->nlimbs;
87  		vsign = v->sign;
88  		wsize = usize + 1;
89  		RESIZE_IF_NEEDED(w, wsize);
90  		/* These must be after realloc (u or v may be the same as w).  */
91  		up = u->d;
92  		vp = v->d;
93  	}
94  	wp = w->d;
95  	wsign = 0;
96  
97  	if (!vsize) {  /* simple */
98  		MPN_COPY(wp, up, usize);
99  		wsize = usize;
100  		wsign = usign;
101  	} else if (usign != vsign) { /* different sign */
102  		/* This test is right since USIZE >= VSIZE */
103  		if (usize != vsize) {
104  			mpihelp_sub(wp, up, usize, vp, vsize);
105  			wsize = usize;
106  			MPN_NORMALIZE(wp, wsize);
107  			wsign = usign;
108  		} else if (mpihelp_cmp(up, vp, usize) < 0) {
109  			mpihelp_sub_n(wp, vp, up, usize);
110  			wsize = usize;
111  			MPN_NORMALIZE(wp, wsize);
112  			if (!usign)
113  				wsign = 1;
114  		} else {
115  			mpihelp_sub_n(wp, up, vp, usize);
116  			wsize = usize;
117  			MPN_NORMALIZE(wp, wsize);
118  			if (usign)
119  				wsign = 1;
120  		}
121  	} else { /* U and V have same sign. Add them. */
122  		mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
123  		wp[usize] = cy;
124  		wsize = usize + cy;
125  		if (usign)
126  			wsign = 1;
127  	}
128  
129  	w->nlimbs = wsize;
130  	w->sign = wsign;
131  }
132  EXPORT_SYMBOL_GPL(mpi_add);
133  
mpi_sub(MPI w,MPI u,MPI v)134  void mpi_sub(MPI w, MPI u, MPI v)
135  {
136  	MPI vv = mpi_copy(v);
137  	vv->sign = !vv->sign;
138  	mpi_add(w, u, vv);
139  	mpi_free(vv);
140  }
141  
142  
mpi_addm(MPI w,MPI u,MPI v,MPI m)143  void mpi_addm(MPI w, MPI u, MPI v, MPI m)
144  {
145  	mpi_add(w, u, v);
146  	mpi_mod(w, w, m);
147  }
148  EXPORT_SYMBOL_GPL(mpi_addm);
149  
mpi_subm(MPI w,MPI u,MPI v,MPI m)150  void mpi_subm(MPI w, MPI u, MPI v, MPI m)
151  {
152  	mpi_sub(w, u, v);
153  	mpi_mod(w, w, m);
154  }
155  EXPORT_SYMBOL_GPL(mpi_subm);
156