summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_add.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_add.c')
-rw-r--r--src/lib/libcrypto/bn/bn_add.c206
1 files changed, 174 insertions, 32 deletions
diff --git a/src/lib/libcrypto/bn/bn_add.c b/src/lib/libcrypto/bn/bn_add.c
index efb2e312e8..6cba07e9f6 100644
--- a/src/lib/libcrypto/bn/bn_add.c
+++ b/src/lib/libcrypto/bn/bn_add.c
@@ -61,76 +61,70 @@
61#include "bn_lcl.h" 61#include "bn_lcl.h"
62 62
63/* r can == a or b */ 63/* r can == a or b */
64int BN_add(r, a, b) 64int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
65BIGNUM *r;
66BIGNUM *a;
67BIGNUM *b;
68 { 65 {
69 int i; 66 const BIGNUM *tmp;
70 BIGNUM *tmp; 67 int a_neg = a->neg;
68
69 bn_check_top(a);
70 bn_check_top(b);
71 71
72 /* a + b a+b 72 /* a + b a+b
73 * a + -b a-b 73 * a + -b a-b
74 * -a + b b-a 74 * -a + b b-a
75 * -a + -b -(a+b) 75 * -a + -b -(a+b)
76 */ 76 */
77 if (a->neg ^ b->neg) 77 if (a_neg ^ b->neg)
78 { 78 {
79 /* only one is negative */ 79 /* only one is negative */
80 if (a->neg) 80 if (a_neg)
81 { tmp=a; a=b; b=tmp; } 81 { tmp=a; a=b; b=tmp; }
82 82
83 /* we are now a - b */ 83 /* we are now a - b */
84 84
85 if (BN_ucmp(a,b) < 0) 85 if (BN_ucmp(a,b) < 0)
86 { 86 {
87 if (bn_wexpand(r,b->top) == NULL) return(0); 87 if (!BN_usub(r,b,a)) return(0);
88 bn_qsub(r,b,a);
89 r->neg=1; 88 r->neg=1;
90 } 89 }
91 else 90 else
92 { 91 {
93 if (bn_wexpand(r,a->top) == NULL) return(0); 92 if (!BN_usub(r,a,b)) return(0);
94 bn_qsub(r,a,b);
95 r->neg=0; 93 r->neg=0;
96 } 94 }
97 return(1); 95 return(1);
98 } 96 }
99 97
100 if (a->neg) /* both are neg */ 98 if (!BN_uadd(r,a,b)) return(0);
99 if (a_neg) /* both are neg */
101 r->neg=1; 100 r->neg=1;
102 else 101 else
103 r->neg=0; 102 r->neg=0;
104
105 i=(a->top > b->top);
106
107 if (i)
108 {
109 if (bn_wexpand(r,a->top+1) == NULL) return(0);
110 bn_qadd(r,a,b);
111 }
112 else
113 {
114 if (bn_wexpand(r,b->top+1) == NULL) return(0);
115 bn_qadd(r,b,a);
116 }
117 return(1); 103 return(1);
118 } 104 }
119 105
120/* unsigned add of b to a, r must be large enough */ 106/* unsigned add of b to a, r must be large enough */
121void bn_qadd(r,a,b) 107int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
122BIGNUM *r;
123BIGNUM *a;
124BIGNUM *b;
125 { 108 {
126 register int i; 109 register int i;
127 int max,min; 110 int max,min;
128 BN_ULONG *ap,*bp,*rp,carry,t1; 111 BN_ULONG *ap,*bp,*rp,carry,t1;
112 const BIGNUM *tmp;
113
114 bn_check_top(a);
115 bn_check_top(b);
129 116
117 if (a->top < b->top)
118 { tmp=a; a=b; b=tmp; }
130 max=a->top; 119 max=a->top;
131 min=b->top; 120 min=b->top;
121
122 if (bn_wexpand(r,max+1) == NULL)
123 return(0);
124
132 r->top=max; 125 r->top=max;
133 126
127
134 ap=a->d; 128 ap=a->d;
135 bp=b->d; 129 bp=b->d;
136 rp=r->d; 130 rp=r->d;
@@ -160,8 +154,156 @@ BIGNUM *b;
160 r->top++; 154 r->top++;
161 } 155 }
162 } 156 }
163 for (; i<max; i++) 157 if (rp != ap)
164 *(rp++)= *(ap++); 158 {
159 for (; i<max; i++)
160 *(rp++)= *(ap++);
161 }
165 /* memcpy(rp,ap,sizeof(*ap)*(max-i));*/ 162 /* memcpy(rp,ap,sizeof(*ap)*(max-i));*/
163 r->neg = 0;
164 return(1);
165 }
166
167/* unsigned subtraction of b from a, a must be larger than b. */
168int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
169 {
170 int max,min;
171 register BN_ULONG t1,t2,*ap,*bp,*rp;
172 int i,carry;
173#if defined(IRIX_CC_BUG) && !defined(LINT)
174 int dummy;
175#endif
176
177 bn_check_top(a);
178 bn_check_top(b);
179
180 if (a->top < b->top) /* hmm... should not be happening */
181 {
182 BNerr(BN_F_BN_USUB,BN_R_ARG2_LT_ARG3);
183 return(0);
184 }
185
186 max=a->top;
187 min=b->top;
188 if (bn_wexpand(r,max) == NULL) return(0);
189
190 ap=a->d;
191 bp=b->d;
192 rp=r->d;
193
194#if 1
195 carry=0;
196 for (i=0; i<min; i++)
197 {
198 t1= *(ap++);
199 t2= *(bp++);
200 if (carry)
201 {
202 carry=(t1 <= t2);
203 t1=(t1-t2-1)&BN_MASK2;
204 }
205 else
206 {
207 carry=(t1 < t2);
208 t1=(t1-t2)&BN_MASK2;
209 }
210#if defined(IRIX_CC_BUG) && !defined(LINT)
211 dummy=t1;
212#endif
213 *(rp++)=t1&BN_MASK2;
214 }
215#else
216 carry=bn_sub_words(rp,ap,bp,min);
217 ap+=min;
218 bp+=min;
219 rp+=min;
220 i=min;
221#endif
222 if (carry) /* subtracted */
223 {
224 while (i < max)
225 {
226 i++;
227 t1= *(ap++);
228 t2=(t1-1)&BN_MASK2;
229 *(rp++)=t2;
230 if (t1 > t2) break;
231 }
232 }
233#if 0
234 memcpy(rp,ap,sizeof(*rp)*(max-i));
235#else
236 if (rp != ap)
237 {
238 for (;;)
239 {
240 if (i++ >= max) break;
241 rp[0]=ap[0];
242 if (i++ >= max) break;
243 rp[1]=ap[1];
244 if (i++ >= max) break;
245 rp[2]=ap[2];
246 if (i++ >= max) break;
247 rp[3]=ap[3];
248 rp+=4;
249 ap+=4;
250 }
251 }
252#endif
253
254 r->top=max;
255 r->neg=0;
256 bn_fix_top(r);
257 return(1);
258 }
259
260int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
261 {
262 int max;
263 int add=0,neg=0;
264 const BIGNUM *tmp;
265
266 bn_check_top(a);
267 bn_check_top(b);
268
269 /* a - b a-b
270 * a - -b a+b
271 * -a - b -(a+b)
272 * -a - -b b-a
273 */
274 if (a->neg)
275 {
276 if (b->neg)
277 { tmp=a; a=b; b=tmp; }
278 else
279 { add=1; neg=1; }
280 }
281 else
282 {
283 if (b->neg) { add=1; neg=0; }
284 }
285
286 if (add)
287 {
288 if (!BN_uadd(r,a,b)) return(0);
289 r->neg=neg;
290 return(1);
291 }
292
293 /* We are actually doing a - b :-) */
294
295 max=(a->top > b->top)?a->top:b->top;
296 if (bn_wexpand(r,max) == NULL) return(0);
297 if (BN_ucmp(a,b) < 0)
298 {
299 if (!BN_usub(r,b,a)) return(0);
300 r->neg=1;
301 }
302 else
303 {
304 if (!BN_usub(r,a,b)) return(0);
305 r->neg=0;
306 }
307 return(1);
166 } 308 }
167 309