summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_div.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_div.c')
-rw-r--r--src/lib/libcrypto/bn/bn_div.c66
1 files changed, 23 insertions, 43 deletions
diff --git a/src/lib/libcrypto/bn/bn_div.c b/src/lib/libcrypto/bn/bn_div.c
index c328b5b411..ac1a09615a 100644
--- a/src/lib/libcrypto/bn/bn_div.c
+++ b/src/lib/libcrypto/bn/bn_div.c
@@ -61,6 +61,7 @@
61#include "cryptlib.h" 61#include "cryptlib.h"
62#include "bn_lcl.h" 62#include "bn_lcl.h"
63 63
64
64/* The old slow way */ 65/* The old slow way */
65#if 0 66#if 0
66int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, 67int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
@@ -126,9 +127,10 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
126 127
127#else 128#else
128 129
129#if !defined(NO_ASM) && !defined(NO_INLINE_ASM) && !defined(PEDANTIC) && !defined(BN_DIV3W) 130#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \
131 && !defined(PEDANTIC) && !defined(BN_DIV3W)
130# if defined(__GNUC__) && __GNUC__>=2 132# if defined(__GNUC__) && __GNUC__>=2
131# if defined(__i386) 133# if defined(__i386) || defined (__i386__)
132 /* 134 /*
133 * There were two reasons for implementing this template: 135 * There were two reasons for implementing this template:
134 * - GNU C generates a call to a function (__udivdi3 to be exact) 136 * - GNU C generates a call to a function (__udivdi3 to be exact)
@@ -150,8 +152,16 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
150# define REMAINDER_IS_ALREADY_CALCULATED 152# define REMAINDER_IS_ALREADY_CALCULATED
151# endif /* __<cpu> */ 153# endif /* __<cpu> */
152# endif /* __GNUC__ */ 154# endif /* __GNUC__ */
153#endif /* NO_ASM */ 155#endif /* OPENSSL_NO_ASM */
156
154 157
158/* BN_div computes dv := num / divisor, rounding towards zero, and sets up
159 * rm such that dv*divisor + rm = num holds.
160 * Thus:
161 * dv->neg == num->neg ^ divisor->neg (unless the result is zero)
162 * rm->neg == num->neg (unless the remainder is zero)
163 * If 'dv' or 'rm' is NULL, the respective value is not returned.
164 */
155int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, 165int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
156 BN_CTX *ctx) 166 BN_CTX *ctx)
157 { 167 {
@@ -185,7 +195,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
185 if (dv == NULL) 195 if (dv == NULL)
186 res=BN_CTX_get(ctx); 196 res=BN_CTX_get(ctx);
187 else res=dv; 197 else res=dv;
188 if (sdiv==NULL || res == NULL) goto err; 198 if (sdiv == NULL || res == NULL) goto err;
189 tmp->neg=0; 199 tmp->neg=0;
190 200
191 /* First we normalise the numbers */ 201 /* First we normalise the numbers */
@@ -232,12 +242,14 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
232 } 242 }
233 else 243 else
234 res->top--; 244 res->top--;
245 if (res->top == 0)
246 res->neg = 0;
235 resp--; 247 resp--;
236 248
237 for (i=0; i<loop-1; i++) 249 for (i=0; i<loop-1; i++)
238 { 250 {
239 BN_ULONG q,l0; 251 BN_ULONG q,l0;
240#if defined(BN_DIV3W) && !defined(NO_ASM) 252#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
241 BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG); 253 BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG);
242 q=bn_div_3_words(wnump,d1,d0); 254 q=bn_div_3_words(wnump,d1,d0);
243#else 255#else
@@ -331,8 +343,13 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
331 } 343 }
332 if (rm != NULL) 344 if (rm != NULL)
333 { 345 {
346 /* Keep a copy of the neg flag in num because if rm==num
347 * BN_rshift() will overwrite it.
348 */
349 int neg = num->neg;
334 BN_rshift(rm,snum,norm_shift); 350 BN_rshift(rm,snum,norm_shift);
335 rm->neg=num->neg; 351 if (!BN_is_zero(rm))
352 rm->neg = neg;
336 } 353 }
337 BN_CTX_end(ctx); 354 BN_CTX_end(ctx);
338 return(1); 355 return(1);
@@ -342,40 +359,3 @@ err:
342 } 359 }
343 360
344#endif 361#endif
345
346/* rem != m */
347int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
348 {
349#if 0 /* The old slow way */
350 int i,nm,nd;
351 BIGNUM *dv;
352
353 if (BN_ucmp(m,d) < 0)
354 return((BN_copy(rem,m) == NULL)?0:1);
355
356 BN_CTX_start(ctx);
357 dv=BN_CTX_get(ctx);
358
359 if (!BN_copy(rem,m)) goto err;
360
361 nm=BN_num_bits(rem);
362 nd=BN_num_bits(d);
363 if (!BN_lshift(dv,d,nm-nd)) goto err;
364 for (i=nm-nd; i>=0; i--)
365 {
366 if (BN_cmp(rem,dv) >= 0)
367 {
368 if (!BN_sub(rem,rem,dv)) goto err;
369 }
370 if (!BN_rshift1(dv,dv)) goto err;
371 }
372 BN_CTX_end(ctx);
373 return(1);
374 err:
375 BN_CTX_end(ctx);
376 return(0);
377#else
378 return(BN_div(NULL,rem,m,d,ctx));
379#endif
380 }
381