summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2023-01-18 05:27:30 +0000
committerjsing <>2023-01-18 05:27:30 +0000
commit84a34f386829f483152f8b71b2cb700f121e54e3 (patch)
treed2f5fac49e73a31624916ab2f448880b2286cd4c
parent52722100e717bb0bc05455878755efbc90d5a4df (diff)
downloadopenbsd-84a34f386829f483152f8b71b2cb700f121e54e3.tar.gz
openbsd-84a34f386829f483152f8b71b2cb700f121e54e3.tar.bz2
openbsd-84a34f386829f483152f8b71b2cb700f121e54e3.zip
Start cleaning up BN_div_internal().
Always provide a bn_div_3_words() function, rather than having deeply nested compiler conditionals. Use readable variable names, clean up formatting and use a single exit path. Tested on various platforms by miod@ ok tb@
-rw-r--r--src/lib/libcrypto/bn/bn_div.c353
1 files changed, 195 insertions, 158 deletions
diff --git a/src/lib/libcrypto/bn/bn_div.c b/src/lib/libcrypto/bn/bn_div.c
index d0adc4688f..7f0560f7c5 100644
--- a/src/lib/libcrypto/bn/bn_div.c
+++ b/src/lib/libcrypto/bn/bn_div.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_div.c,v 1.29 2022/12/26 07:18:51 jmc Exp $ */ 1/* $OpenBSD: bn_div.c,v 1.30 2023/01/18 05:27:30 jsing 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 *
@@ -65,8 +65,11 @@
65 65
66#include "bn_local.h" 66#include "bn_local.h"
67 67
68#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \ 68BN_ULONG bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0);
69 && !defined(BN_DIV3W) 69
70#ifndef BN_DIV3W
71
72#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
70# if defined(__GNUC__) && __GNUC__>=2 73# if defined(__GNUC__) && __GNUC__>=2
71# if defined(__i386) || defined (__i386__) 74# if defined(__i386) || defined (__i386__)
72 /* 75 /*
@@ -108,17 +111,102 @@
108# endif /* __GNUC__ */ 111# endif /* __GNUC__ */
109#endif /* OPENSSL_NO_ASM */ 112#endif /* OPENSSL_NO_ASM */
110 113
114BN_ULONG
115bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0)
116{
117 BN_ULONG n0, n1, q;
118 BN_ULONG rem = 0;
119
120 n0 = m[0];
121 n1 = m[-1];
122
123 if (n0 == d0)
124 return BN_MASK2;
125
126 /* n0 < d0 */
127 {
128#ifdef BN_LLONG
129 BN_ULLONG t2;
111 130
112/* BN_div computes dv := num / divisor, rounding towards 131#if defined(BN_DIV2W) && !defined(bn_div_words)
113 * zero, and sets up rm such that dv*divisor + rm = num holds. 132 q = (BN_ULONG)((((BN_ULLONG)n0 << BN_BITS2) | n1) / d0);
114 * Thus: 133#else
115 * dv->neg == num->neg ^ divisor->neg (unless the result is zero) 134 q = bn_div_words(n0, n1, d0);
116 * rm->neg == num->neg (unless the remainder is zero) 135#endif
117 * If 'dv' or 'rm' is NULL, the respective value is not returned. 136
137#ifndef REMAINDER_IS_ALREADY_CALCULATED
138 /*
139 * rem doesn't have to be BN_ULLONG. The least we
140 * know it's less that d0, isn't it?
141 */
142 rem = (n1 - q * d0) & BN_MASK2;
143#endif
144 t2 = (BN_ULLONG)d1 * q;
145
146 for (;;) {
147 if (t2 <= (((BN_ULLONG)rem << BN_BITS2) | m[-2]))
148 break;
149 q--;
150 rem += d0;
151 if (rem < d0) break; /* don't let rem overflow */
152 t2 -= d1;
153 }
154#else /* !BN_LLONG */
155 BN_ULONG t2l, t2h;
156
157 q = bn_div_words(n0, n1, d0);
158#ifndef REMAINDER_IS_ALREADY_CALCULATED
159 rem = (n1 - q * d0) & BN_MASK2;
160#endif
161
162#if defined(BN_UMULT_LOHI)
163 BN_UMULT_LOHI(t2l, t2h, d1, q);
164#elif defined(BN_UMULT_HIGH)
165 t2l = d1 * q;
166 t2h = BN_UMULT_HIGH(d1, q);
167#else
168 {
169 BN_ULONG ql, qh;
170 t2l = LBITS(d1);
171 t2h = HBITS(d1);
172 ql = LBITS(q);
173 qh = HBITS(q);
174 mul64(t2l, t2h, ql, qh); /* t2 = (BN_ULLONG)d1 * q; */
175 }
176#endif
177
178 for (;;) {
179 if (t2h < rem || (t2h == rem && t2l <= m[-2]))
180 break;
181 q--;
182 rem += d0;
183 if (rem < d0)
184 break; /* don't let rem overflow */
185 if (t2l < d1)
186 t2h--;
187 t2l -= d1;
188 }
189#endif /* !BN_LLONG */
190 }
191
192 return q;
193}
194#endif /* !BN_DIV3W */
195
196/*
197 * BN_div_internal computes quotient := numerator / divisor, rounding towards
198 * zero and setting remainder such that quotient * divisor + remainder equals
199 * the numerator. Thus:
200 *
201 * quotient->neg == numerator->neg ^ divisor->neg (unless result is zero)
202 * remainder->neg == numerator->neg (unless the remainder is zero)
203 *
204 * If either the quotient or remainder is NULL, the respective value is not
205 * returned.
118 */ 206 */
119static int 207static int
120BN_div_internal(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, 208BN_div_internal(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
121 BN_CTX *ctx, int ct) 209 const BIGNUM *divisor, BN_CTX *ctx, int ct)
122{ 210{
123 int norm_shift, i, loop; 211 int norm_shift, i, loop;
124 BIGNUM *tmp, wnum, *snum, *sdiv, *res; 212 BIGNUM *tmp, wnum, *snum, *sdiv, *res;
@@ -126,58 +214,62 @@ BN_div_internal(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor
126 BN_ULONG d0, d1; 214 BN_ULONG d0, d1;
127 int num_n, div_n; 215 int num_n, div_n;
128 int no_branch = 0; 216 int no_branch = 0;
217 int ret = 0;
218
219 BN_CTX_start(ctx);
129 220
130 /* Invalid zero-padding would have particularly bad consequences. */ 221 /* Invalid zero-padding would have particularly bad consequences. */
131 if (num->top > 0 && num->d[num->top - 1] == 0) { 222 if (numerator->top > 0 && numerator->d[numerator->top - 1] == 0) {
132 BNerror(BN_R_NOT_INITIALIZED); 223 BNerror(BN_R_NOT_INITIALIZED);
133 return 0; 224 goto err;
134 } 225 }
135 226
136
137 if (ct) 227 if (ct)
138 no_branch = 1; 228 no_branch = 1;
139 229
140
141 if (BN_is_zero(divisor)) { 230 if (BN_is_zero(divisor)) {
142 BNerror(BN_R_DIV_BY_ZERO); 231 BNerror(BN_R_DIV_BY_ZERO);
143 return (0); 232 goto err;
144 } 233 }
145 234
146 if (!no_branch && BN_ucmp(num, divisor) < 0) { 235 if (!no_branch) {
147 if (rm != NULL) { 236 if (BN_ucmp(numerator, divisor) < 0) {
148 if (BN_copy(rm, num) == NULL) 237 if (remainder != NULL) {
149 return (0); 238 if (BN_copy(remainder, numerator) == NULL)
239 goto err;
240 }
241 if (quotient != NULL)
242 BN_zero(quotient);
243
244 goto done;
150 } 245 }
151 if (dv != NULL)
152 BN_zero(dv);
153 return (1);
154 } 246 }
155 247
156 BN_CTX_start(ctx); 248 if ((tmp = BN_CTX_get(ctx)) == NULL)
157 tmp = BN_CTX_get(ctx); 249 goto err;
158 snum = BN_CTX_get(ctx); 250 if ((snum = BN_CTX_get(ctx)) == NULL)
159 sdiv = BN_CTX_get(ctx); 251 goto err;
160 if (dv == NULL) 252 if ((sdiv = BN_CTX_get(ctx)) == NULL)
161 res = BN_CTX_get(ctx);
162 else
163 res = dv;
164 if (tmp == NULL || snum == NULL || sdiv == NULL || res == NULL)
165 goto err; 253 goto err;
254 if ((res = quotient) == NULL) {
255 if ((res = BN_CTX_get(ctx)) == NULL)
256 goto err;
257 }
166 258
167 /* First we normalise the numbers */ 259 /* First we normalise the numbers. */
168 norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2); 260 norm_shift = BN_BITS2 - BN_num_bits(divisor) % BN_BITS2;
169 if (!(BN_lshift(sdiv, divisor, norm_shift))) 261 if (!BN_lshift(sdiv, divisor, norm_shift))
170 goto err; 262 goto err;
171 sdiv->neg = 0; 263 sdiv->neg = 0;
172 norm_shift += BN_BITS2; 264 norm_shift += BN_BITS2;
173 if (!(BN_lshift(snum, num, norm_shift))) 265 if (!BN_lshift(snum, numerator, norm_shift))
174 goto err; 266 goto err;
175 snum->neg = 0; 267 snum->neg = 0;
176 268
177 if (no_branch) { 269 if (no_branch) {
178 /* Since we don't know whether snum is larger than sdiv, 270 /*
179 * we pad snum with enough zeroes without changing its 271 * Since we don't know whether snum is larger than sdiv, we pad
180 * value. 272 * snum with enough zeroes without changing its value.
181 */ 273 */
182 if (snum->top <= sdiv->top + 1) { 274 if (snum->top <= sdiv->top + 1) {
183 if (!bn_wexpand(snum, sdiv->top + 2)) 275 if (!bn_wexpand(snum, sdiv->top + 2))
@@ -189,16 +281,18 @@ BN_div_internal(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor
189 if (!bn_wexpand(snum, snum->top + 1)) 281 if (!bn_wexpand(snum, snum->top + 1))
190 goto err; 282 goto err;
191 snum->d[snum->top] = 0; 283 snum->d[snum->top] = 0;
192 snum->top ++; 284 snum->top++;
193 } 285 }
194 } 286 }
195 287
196 div_n = sdiv->top; 288 div_n = sdiv->top;
197 num_n = snum->top; 289 num_n = snum->top;
198 loop = num_n - div_n; 290 loop = num_n - div_n;
199 /* Lets setup a 'window' into snum 291
200 * This is the part that corresponds to the current 292 /*
201 * 'area' being divided */ 293 * Setup a 'window' into snum - this is the part that corresponds to the
294 * current 'area' being divided.
295 */
202 wnum.neg = 0; 296 wnum.neg = 0;
203 wnum.d = &(snum->d[loop]); 297 wnum.d = &(snum->d[loop]);
204 wnum.top = div_n; 298 wnum.top = div_n;
@@ -215,7 +309,7 @@ BN_div_internal(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor
215 wnump = &(snum->d[num_n - 1]); 309 wnump = &(snum->d[num_n - 1]);
216 310
217 /* Setup to 'res' */ 311 /* Setup to 'res' */
218 res->neg = (num->neg ^ divisor->neg); 312 res->neg = (numerator->neg ^ divisor->neg);
219 if (!bn_wexpand(res, (loop + 1))) 313 if (!bn_wexpand(res, (loop + 1)))
220 goto err; 314 goto err;
221 res->top = loop - no_branch; 315 res->top = loop - no_branch;
@@ -233,8 +327,10 @@ BN_div_internal(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor
233 res->top--; 327 res->top--;
234 } 328 }
235 329
236 /* if res->top == 0 then clear the neg value otherwise decrease 330 /*
237 * the resp pointer */ 331 * If res->top == 0 then clear the neg value otherwise decrease the resp
332 * pointer.
333 */
238 if (res->top == 0) 334 if (res->top == 0)
239 res->neg = 0; 335 res->neg = 0;
240 else 336 else
@@ -242,149 +338,90 @@ BN_div_internal(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor
242 338
243 for (i = 0; i < loop - 1; i++, wnump--, resp--) { 339 for (i = 0; i < loop - 1; i++, wnump--, resp--) {
244 BN_ULONG q, l0; 340 BN_ULONG q, l0;
245 /* the first part of the loop uses the top two words of
246 * snum and sdiv to calculate a BN_ULONG q such that
247 * | wnum - sdiv * q | < sdiv */
248#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
249 BN_ULONG bn_div_3_words(BN_ULONG*, BN_ULONG, BN_ULONG);
250 q = bn_div_3_words(wnump, d1, d0);
251#else
252 BN_ULONG n0, n1, rem = 0;
253
254 n0 = wnump[0];
255 n1 = wnump[-1];
256 if (n0 == d0)
257 q = BN_MASK2;
258 else /* n0 < d0 */
259 {
260#ifdef BN_LLONG
261 BN_ULLONG t2;
262
263#if defined(BN_DIV2W) && !defined(bn_div_words)
264 q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2)|n1)/d0);
265#else
266 q = bn_div_words(n0, n1, d0);
267#endif
268
269#ifndef REMAINDER_IS_ALREADY_CALCULATED
270 /*
271 * rem doesn't have to be BN_ULLONG. The least we
272 * know it's less that d0, isn't it?
273 */
274 rem = (n1 - q * d0) & BN_MASK2;
275#endif
276 t2 = (BN_ULLONG)d1*q;
277
278 for (;;) {
279 if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) |
280 wnump[-2]))
281 break;
282 q--;
283 rem += d0;
284 if (rem < d0) break; /* don't let rem overflow */
285 t2 -= d1;
286 }
287#else /* !BN_LLONG */
288 BN_ULONG t2l, t2h;
289
290 q = bn_div_words(n0, n1, d0);
291#ifndef REMAINDER_IS_ALREADY_CALCULATED
292 rem = (n1 - q*d0)&BN_MASK2;
293#endif
294
295#if defined(BN_UMULT_LOHI)
296 BN_UMULT_LOHI(t2l, t2h, d1, q);
297#elif defined(BN_UMULT_HIGH)
298 t2l = d1 * q;
299 t2h = BN_UMULT_HIGH(d1, q);
300#else
301 {
302 BN_ULONG ql, qh;
303 t2l = LBITS(d1);
304 t2h = HBITS(d1);
305 ql = LBITS(q);
306 qh = HBITS(q);
307 mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */
308 }
309#endif
310
311 for (;;) {
312 if ((t2h < rem) ||
313 ((t2h == rem) && (t2l <= wnump[-2])))
314 break;
315 q--;
316 rem += d0;
317 if (rem < d0)
318 break; /* don't let rem overflow */
319 if (t2l < d1)
320 t2h--;
321 t2l -= d1;
322 }
323#endif /* !BN_LLONG */
324 }
325#endif /* !BN_DIV3W */
326 341
342 /*
343 * The first part of the loop uses the top two words of snum and
344 * sdiv to calculate a BN_ULONG q such that:
345 *
346 * | wnum - sdiv * q | < sdiv
347 */
348 q = bn_div_3_words(wnump, d1, d0);
327 l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q); 349 l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
328 tmp->d[div_n] = l0; 350 tmp->d[div_n] = l0;
329 wnum.d--; 351 wnum.d--;
330 /* ignore top values of the bignums just sub the two 352
331 * BN_ULONG arrays with bn_sub_words */ 353 /*
354 * Ignore top values of the bignums just sub the two BN_ULONG
355 * arrays with bn_sub_words.
356 */
332 if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) { 357 if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) {
333 /* Note: As we have considered only the leading 358 /*
334 * two BN_ULONGs in the calculation of q, sdiv * q 359 * Note: As we have considered only the leading two
335 * might be greater than wnum (but then (q-1) * sdiv 360 * BN_ULONGs in the calculation of q, sdiv * q might be
336 * is less or equal than wnum) 361 * greater than wnum (but then (q-1) * sdiv is less or
362 * equal than wnum).
337 */ 363 */
338 q--; 364 q--;
339 if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) 365 if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) {
340 /* we can't have an overflow here (assuming 366 /*
367 * We can't have an overflow here (assuming
341 * that q != 0, but if q == 0 then tmp is 368 * that q != 0, but if q == 0 then tmp is
342 * zero anyway) */ 369 * zero anyway).
370 */
343 (*wnump)++; 371 (*wnump)++;
372 }
344 } 373 }
345 /* store part of the result */ 374 /* store part of the result */
346 *resp = q; 375 *resp = q;
347 } 376 }
377
348 bn_correct_top(snum); 378 bn_correct_top(snum);
349 if (rm != NULL) { 379
350 /* Keep a copy of the neg flag in num because if rm==num 380 if (remainder != NULL) {
351 * BN_rshift() will overwrite it. 381 /*
382 * Keep a copy of the neg flag in numerator because if
383 * remainder == numerator, BN_rshift() will overwrite it.
352 */ 384 */
353 int neg = num->neg; 385 int neg = numerator->neg;
354 BN_rshift(rm, snum, norm_shift); 386
355 if (!BN_is_zero(rm)) 387 BN_rshift(remainder, snum, norm_shift);
356 rm->neg = neg; 388 if (!BN_is_zero(remainder))
389 remainder->neg = neg;
357 } 390 }
391
358 if (no_branch) 392 if (no_branch)
359 bn_correct_top(res); 393 bn_correct_top(res);
360 BN_CTX_end(ctx);
361 return (1);
362 394
363err: 395 done:
396 ret = 1;
397 err:
364 BN_CTX_end(ctx); 398 BN_CTX_end(ctx);
365 return (0); 399
400 return ret;
366} 401}
367 402
368int 403int
369BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, 404BN_div(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
370 BN_CTX *ctx) 405 const BIGNUM *divisor, BN_CTX *ctx)
371{ 406{
372 int ct = ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0) || 407 int ct;
373 (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0)); 408
409 ct = BN_get_flags(numerator, BN_FLG_CONSTTIME) != 0 ||
410 BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0;
374 411
375 return BN_div_internal(dv, rm, num, divisor, ctx, ct); 412 return BN_div_internal(quotient, remainder, numerator, divisor, ctx, ct);
376} 413}
377 414
378int 415int
379BN_div_nonct(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, 416BN_div_nonct(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
380 BN_CTX *ctx) 417 const BIGNUM *divisor, BN_CTX *ctx)
381{ 418{
382 return BN_div_internal(dv, rm, num, divisor, ctx, 0); 419 return BN_div_internal(quotient, remainder, numerator, divisor, ctx, 0);
383} 420}
384 421
385int 422int
386BN_div_ct(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, 423BN_div_ct(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
387 BN_CTX *ctx) 424 const BIGNUM *divisor, BN_CTX *ctx)
388{ 425{
389 return BN_div_internal(dv, rm, num, divisor, ctx, 1); 426 return BN_div_internal(quotient, remainder, numerator, divisor, ctx, 1);
390} 427}