summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2018-07-23 18:07:21 +0000
committertb <>2018-07-23 18:07:21 +0000
commit6549dc05f9ea0cb21d1e921b85864d1ce4646e0c (patch)
treecb61671ed4b7e4c4812fc32b132f366be33ad74e
parentb198bfa529da4219036fbc6bb5722566a59e9dd7 (diff)
downloadopenbsd-6549dc05f9ea0cb21d1e921b85864d1ce4646e0c.tar.gz
openbsd-6549dc05f9ea0cb21d1e921b85864d1ce4646e0c.tar.bz2
openbsd-6549dc05f9ea0cb21d1e921b85864d1ce4646e0c.zip
Clean up our disgusting implementations of BN_{,u}{add,sub}(), following
changes made in OpenSSL by Davide Galassi and others, so that one can actually follow what is going on. There is no performance impact from this change as the code still does essentially the same thing. There's a ton of work still to be done to make the BN code less terrible. ok jsing, kn
-rw-r--r--src/lib/libcrypto/bn/bn_add.c224
1 files changed, 67 insertions, 157 deletions
diff --git a/src/lib/libcrypto/bn/bn_add.c b/src/lib/libcrypto/bn/bn_add.c
index 2e82d280ec..048a136b95 100644
--- a/src/lib/libcrypto/bn/bn_add.c
+++ b/src/lib/libcrypto/bn/bn_add.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_add.c,v 1.12 2018/06/10 19:38:19 tb Exp $ */ 1/* $OpenBSD: bn_add.c,v 1.13 2018/07/23 18:07:21 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -62,61 +62,51 @@
62 62
63#include "bn_lcl.h" 63#include "bn_lcl.h"
64 64
65/* r can == a or b */
66int 65int
67BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) 66BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
68{ 67{
69 const BIGNUM *tmp; 68 int ret, r_neg;
70 int a_neg = a->neg, ret;
71 69
72 bn_check_top(a); 70 bn_check_top(a);
73 bn_check_top(b); 71 bn_check_top(b);
74 72
75 /* a + b a+b 73 if (a->neg == b->neg) {
76 * a + -b a-b 74 r_neg = a->neg;
77 * -a + b b-a 75 ret = BN_uadd(r, a, b);
78 * -a + -b -(a+b) 76 } else {
79 */ 77 int cmp = BN_ucmp(a, b);
80 if (a_neg ^ b->neg) { 78
81 /* only one is negative */ 79 if (cmp > 0) {
82 if (a_neg) { 80 r_neg = a->neg;
83 tmp = a; 81 ret = BN_usub(r, a, b);
84 a = b; 82 } else if (cmp < 0) {
85 b = tmp; 83 r_neg = b->neg;
86 } 84 ret = BN_usub(r, b, a);
87
88 /* we are now a - b */
89
90 if (BN_ucmp(a, b) < 0) {
91 if (!BN_usub(r, b, a))
92 return (0);
93 r->neg = 1;
94 } else { 85 } else {
95 if (!BN_usub(r, a, b)) 86 r_neg = 0;
96 return (0); 87 BN_zero(r);
97 r->neg = 0; 88 ret = 1;
98 } 89 }
99 return (1);
100 } 90 }
101 91
102 ret = BN_uadd(r, a, b); 92 r->neg = r_neg;
103 r->neg = a_neg;
104 bn_check_top(r); 93 bn_check_top(r);
105 return ret; 94 return ret;
106} 95}
107 96
108/* unsigned add of b to a */
109int 97int
110BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) 98BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
111{ 99{
112 int max, min, dif; 100 int max, min, dif;
113 BN_ULONG *ap, *bp, *rp, carry, t1, t2; 101 const BN_ULONG *ap, *bp;
114 const BIGNUM *tmp; 102 BN_ULONG *rp, carry, t1, t2;
115 103
116 bn_check_top(a); 104 bn_check_top(a);
117 bn_check_top(b); 105 bn_check_top(b);
118 106
119 if (a->top < b->top) { 107 if (a->top < b->top) {
108 const BIGNUM *tmp;
109
120 tmp = a; 110 tmp = a;
121 a = b; 111 a = b;
122 b = tmp; 112 b = tmp;
@@ -137,41 +127,28 @@ BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
137 carry = bn_add_words(rp, ap, bp, min); 127 carry = bn_add_words(rp, ap, bp, min);
138 rp += min; 128 rp += min;
139 ap += min; 129 ap += min;
140 bp += min; 130
141 131 while (dif) {
142 if (carry) { 132 dif--;
143 while (dif) { 133 t1 = *(ap++);
144 dif--; 134 t2 = (t1 + carry) & BN_MASK2;
145 t1 = *(ap++); 135 *(rp++) = t2;
146 t2 = (t1 + 1) & BN_MASK2; 136 carry &= (t2 == 0);
147 *(rp++) = t2;
148 if (t2) {
149 carry = 0;
150 break;
151 }
152 }
153 if (carry) {
154 /* carry != 0 => dif == 0 */
155 *rp = 1;
156 r->top++;
157 }
158 } 137 }
159 if (dif && rp != ap) 138 *rp = carry;
160 while (dif--) 139 r->top += carry;
161 /* copy remaining words if ap != rp */ 140
162 *(rp++) = *(ap++);
163 r->neg = 0; 141 r->neg = 0;
164 bn_check_top(r); 142 bn_check_top(r);
165 return 1; 143 return 1;
166} 144}
167 145
168/* unsigned subtraction of b from a, a must be larger than b. */
169int 146int
170BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) 147BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
171{ 148{
172 int max, min, dif; 149 int max, min, dif;
173 BN_ULONG t1, t2, *ap, *bp, *rp; 150 const BN_ULONG *ap, *bp;
174 int i, carry; 151 BN_ULONG t1, t2, borrow, *rp;
175 152
176 bn_check_top(a); 153 bn_check_top(a);
177 bn_check_top(b); 154 bn_check_top(b);
@@ -180,134 +157,67 @@ BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
180 min = b->top; 157 min = b->top;
181 dif = max - min; 158 dif = max - min;
182 159
183 if (dif < 0) /* hmm... should not be happening */ 160 if (dif < 0) {
184 {
185 BNerror(BN_R_ARG2_LT_ARG3); 161 BNerror(BN_R_ARG2_LT_ARG3);
186 return (0); 162 return 0;
187 } 163 }
188 164
189 if (bn_wexpand(r, max) == NULL) 165 if (bn_wexpand(r, max) == NULL)
190 return (0); 166 return 0;
191 167
192 ap = a->d; 168 ap = a->d;
193 bp = b->d; 169 bp = b->d;
194 rp = r->d; 170 rp = r->d;
195 171
196#if 1 172 borrow = bn_sub_words(rp, ap, bp, min);
197 carry = 0;
198 for (i = min; i != 0; i--) {
199 t1= *(ap++);
200 t2= *(bp++);
201 if (carry) {
202 carry = (t1 <= t2);
203 t1 = (t1 - t2 - 1)&BN_MASK2;
204 } else {
205 carry = (t1 < t2);
206 t1 = (t1 - t2)&BN_MASK2;
207 }
208 *(rp++) = t1&BN_MASK2;
209 }
210#else
211 carry = bn_sub_words(rp, ap, bp, min);
212 ap += min; 173 ap += min;
213 bp += min;
214 rp += min; 174 rp += min;
215#endif 175
216 if (carry) /* subtracted */ 176 while (dif) {
217 { 177 dif--;
218 if (!dif) 178 t1 = *(ap++);
219 /* error: a < b */ 179 t2 = (t1 - borrow) & BN_MASK2;
220 return 0; 180 *(rp++) = t2;
221 while (dif) { 181 borrow &= (t1 == 0);
222 dif--;
223 t1 = *(ap++);
224 t2 = (t1 - 1)&BN_MASK2;
225 *(rp++) = t2;
226 if (t1)
227 break;
228 }
229 }
230#if 0
231 memcpy(rp, ap, sizeof(*rp)*(max - i));
232#else
233 if (rp != ap) {
234 for (;;) {
235 if (!dif--)
236 break;
237 rp[0] = ap[0];
238 if (!dif--)
239 break;
240 rp[1] = ap[1];
241 if (!dif--)
242 break;
243 rp[2] = ap[2];
244 if (!dif--)
245 break;
246 rp[3] = ap[3];
247 rp += 4;
248 ap += 4;
249 }
250 } 182 }
251#endif 183
184 while (max > 0 && *--rp == 0)
185 max--;
252 186
253 r->top = max; 187 r->top = max;
254 r->neg = 0; 188 r->neg = 0;
255 bn_correct_top(r); 189 bn_correct_top(r);
256 return (1); 190 return 1;
257} 191}
258 192
259int 193int
260BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) 194BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
261{ 195{
262 int max; 196 int ret, r_neg;
263 int add = 0, neg = 0;
264 const BIGNUM *tmp;
265 197
266 bn_check_top(a); 198 bn_check_top(a);
267 bn_check_top(b); 199 bn_check_top(b);
268 200
269 /* a - b a-b 201 if (a->neg != b->neg) {
270 * a - -b a+b 202 r_neg = a->neg;
271 * -a - b -(a+b) 203 ret = BN_uadd(r, a, b);
272 * -a - -b b-a
273 */
274 if (a->neg) {
275 if (b->neg) {
276 tmp = a;
277 a = b;
278 b = tmp;
279 } else {
280 add = 1;
281 neg = 1;
282 }
283 } else { 204 } else {
284 if (b->neg) { 205 int cmp = BN_ucmp(a, b);
285 add = 1; 206
286 neg = 0; 207 if (cmp > 0) {
208 r_neg = a->neg;
209 ret = BN_usub(r, a, b);
210 } else if (cmp < 0) {
211 r_neg = !b->neg;
212 ret = BN_usub(r, b, a);
213 } else {
214 r_neg = 0;
215 BN_zero(r);
216 ret = 1;
287 } 217 }
288 } 218 }
289 219
290 if (add) { 220 r->neg = r_neg;
291 if (!BN_uadd(r, a, b))
292 return (0);
293 r->neg = neg;
294 return (1);
295 }
296
297 /* We are actually doing a - b :-) */
298
299 max = (a->top > b->top) ? a->top : b->top;
300 if (bn_wexpand(r, max) == NULL)
301 return (0);
302 if (BN_ucmp(a, b) < 0) {
303 if (!BN_usub(r, b, a))
304 return (0);
305 r->neg = 1;
306 } else {
307 if (!BN_usub(r, a, b))
308 return (0);
309 r->neg = 0;
310 }
311 bn_check_top(r); 221 bn_check_top(r);
312 return (1); 222 return ret;
313} 223}