os/ossrv/ssl/libcrypto/src/crypto/bn/bn_div.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/bn/bn_div.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
sl@0
    59
#include <stdio.h>
sl@0
    60
#include <openssl/bn.h>
sl@0
    61
#include "cryptlib.h"
sl@0
    62
#include "bn_lcl.h"
sl@0
    63
sl@0
    64
sl@0
    65
/* The old slow way */
sl@0
    66
#if 0
sl@0
    67
EXPORT_C int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
sl@0
    68
	   BN_CTX *ctx)
sl@0
    69
	{
sl@0
    70
	int i,nm,nd;
sl@0
    71
	int ret = 0;
sl@0
    72
	BIGNUM *D;
sl@0
    73
sl@0
    74
	bn_check_top(m);
sl@0
    75
	bn_check_top(d);
sl@0
    76
	if (BN_is_zero(d))
sl@0
    77
		{
sl@0
    78
		BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO);
sl@0
    79
		return(0);
sl@0
    80
		}
sl@0
    81
sl@0
    82
	if (BN_ucmp(m,d) < 0)
sl@0
    83
		{
sl@0
    84
		if (rem != NULL)
sl@0
    85
			{ if (BN_copy(rem,m) == NULL) return(0); }
sl@0
    86
		if (dv != NULL) BN_zero(dv);
sl@0
    87
		return(1);
sl@0
    88
		}
sl@0
    89
sl@0
    90
	BN_CTX_start(ctx);
sl@0
    91
	D = BN_CTX_get(ctx);
sl@0
    92
	if (dv == NULL) dv = BN_CTX_get(ctx);
sl@0
    93
	if (rem == NULL) rem = BN_CTX_get(ctx);
sl@0
    94
	if (D == NULL || dv == NULL || rem == NULL)
sl@0
    95
		goto end;
sl@0
    96
sl@0
    97
	nd=BN_num_bits(d);
sl@0
    98
	nm=BN_num_bits(m);
sl@0
    99
	if (BN_copy(D,d) == NULL) goto end;
sl@0
   100
	if (BN_copy(rem,m) == NULL) goto end;
sl@0
   101
sl@0
   102
	/* The next 2 are needed so we can do a dv->d[0]|=1 later
sl@0
   103
	 * since BN_lshift1 will only work once there is a value :-) */
sl@0
   104
	BN_zero(dv);
sl@0
   105
	bn_wexpand(dv,1);
sl@0
   106
	dv->top=1;
sl@0
   107
sl@0
   108
	if (!BN_lshift(D,D,nm-nd)) goto end;
sl@0
   109
	for (i=nm-nd; i>=0; i--)
sl@0
   110
		{
sl@0
   111
		if (!BN_lshift1(dv,dv)) goto end;
sl@0
   112
		if (BN_ucmp(rem,D) >= 0)
sl@0
   113
			{
sl@0
   114
			dv->d[0]|=1;
sl@0
   115
			if (!BN_usub(rem,rem,D)) goto end;
sl@0
   116
			}
sl@0
   117
/* CAN IMPROVE (and have now :=) */
sl@0
   118
		if (!BN_rshift1(D,D)) goto end;
sl@0
   119
		}
sl@0
   120
	rem->neg=BN_is_zero(rem)?0:m->neg;
sl@0
   121
	dv->neg=m->neg^d->neg;
sl@0
   122
	ret = 1;
sl@0
   123
 end:
sl@0
   124
	BN_CTX_end(ctx);
sl@0
   125
	return(ret);
sl@0
   126
	}
sl@0
   127
sl@0
   128
#else
sl@0
   129
sl@0
   130
#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \
sl@0
   131
    && !defined(PEDANTIC) && !defined(BN_DIV3W)
sl@0
   132
# if defined(__GNUC__) && __GNUC__>=2
sl@0
   133
#  if defined(__i386) || defined (__i386__)
sl@0
   134
   /*
sl@0
   135
    * There were two reasons for implementing this template:
sl@0
   136
    * - GNU C generates a call to a function (__udivdi3 to be exact)
sl@0
   137
    *   in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
sl@0
   138
    *   understand why...);
sl@0
   139
    * - divl doesn't only calculate quotient, but also leaves
sl@0
   140
    *   remainder in %edx which we can definitely use here:-)
sl@0
   141
    *
sl@0
   142
    *					<appro@fy.chalmers.se>
sl@0
   143
    */
sl@0
   144
#  define bn_div_words(n0,n1,d0)		\
sl@0
   145
	({  asm volatile (			\
sl@0
   146
		"divl	%4"			\
sl@0
   147
		: "=a"(q), "=d"(rem)		\
sl@0
   148
		: "a"(n1), "d"(n0), "g"(d0)	\
sl@0
   149
		: "cc");			\
sl@0
   150
	    q;					\
sl@0
   151
	})
sl@0
   152
#  define REMAINDER_IS_ALREADY_CALCULATED
sl@0
   153
#  elif defined(__x86_64) && defined(SIXTY_FOUR_BIT_LONG)
sl@0
   154
   /*
sl@0
   155
    * Same story here, but it's 128-bit by 64-bit division. Wow!
sl@0
   156
    *					<appro@fy.chalmers.se>
sl@0
   157
    */
sl@0
   158
#  define bn_div_words(n0,n1,d0)		\
sl@0
   159
	({  asm volatile (			\
sl@0
   160
		"divq	%4"			\
sl@0
   161
		: "=a"(q), "=d"(rem)		\
sl@0
   162
		: "a"(n1), "d"(n0), "g"(d0)	\
sl@0
   163
		: "cc");			\
sl@0
   164
	    q;					\
sl@0
   165
	})
sl@0
   166
#  define REMAINDER_IS_ALREADY_CALCULATED
sl@0
   167
#  endif /* __<cpu> */
sl@0
   168
# endif /* __GNUC__ */
sl@0
   169
#endif /* OPENSSL_NO_ASM */
sl@0
   170
sl@0
   171
sl@0
   172
/* BN_div[_no_branch] computes  dv := num / divisor,  rounding towards
sl@0
   173
 * zero, and sets up rm  such that  dv*divisor + rm = num  holds.
sl@0
   174
 * Thus:
sl@0
   175
 *     dv->neg == num->neg ^ divisor->neg  (unless the result is zero)
sl@0
   176
 *     rm->neg == num->neg                 (unless the remainder is zero)
sl@0
   177
 * If 'dv' or 'rm' is NULL, the respective value is not returned.
sl@0
   178
 */
sl@0
   179
static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
sl@0
   180
        const BIGNUM *divisor, BN_CTX *ctx);
sl@0
   181
EXPORT_C int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
sl@0
   182
	   BN_CTX *ctx)
sl@0
   183
	{
sl@0
   184
	int norm_shift,i,loop;
sl@0
   185
	BIGNUM *tmp,wnum,*snum,*sdiv,*res;
sl@0
   186
	BN_ULONG *resp,*wnump;
sl@0
   187
	BN_ULONG d0,d1;
sl@0
   188
	int num_n,div_n;
sl@0
   189
	if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0))
sl@0
   190
		{
sl@0
   191
		return BN_div_no_branch(dv, rm, num, divisor, ctx);
sl@0
   192
		}
sl@0
   193
sl@0
   194
	bn_check_top(dv);
sl@0
   195
	bn_check_top(rm);
sl@0
   196
	bn_check_top(num);
sl@0
   197
	bn_check_top(divisor);
sl@0
   198
sl@0
   199
	if (BN_is_zero(divisor))
sl@0
   200
		{
sl@0
   201
		BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO);
sl@0
   202
		return(0);
sl@0
   203
		}
sl@0
   204
sl@0
   205
	if (BN_ucmp(num,divisor) < 0)
sl@0
   206
		{
sl@0
   207
		if (rm != NULL)
sl@0
   208
			{ if (BN_copy(rm,num) == NULL) return(0); }
sl@0
   209
		if (dv != NULL) BN_zero(dv);
sl@0
   210
		return(1);
sl@0
   211
		}
sl@0
   212
sl@0
   213
	BN_CTX_start(ctx);
sl@0
   214
	tmp=BN_CTX_get(ctx);
sl@0
   215
	snum=BN_CTX_get(ctx);
sl@0
   216
	sdiv=BN_CTX_get(ctx);
sl@0
   217
	if (dv == NULL)
sl@0
   218
		res=BN_CTX_get(ctx);
sl@0
   219
	else	res=dv;
sl@0
   220
	if (sdiv == NULL || res == NULL) goto err;
sl@0
   221
sl@0
   222
	/* First we normalise the numbers */
sl@0
   223
	norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2);
sl@0
   224
	if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err;
sl@0
   225
	sdiv->neg=0;
sl@0
   226
	norm_shift+=BN_BITS2;
sl@0
   227
	if (!(BN_lshift(snum,num,norm_shift))) goto err;
sl@0
   228
	snum->neg=0;
sl@0
   229
	div_n=sdiv->top;
sl@0
   230
	num_n=snum->top;
sl@0
   231
	loop=num_n-div_n;
sl@0
   232
	/* Lets setup a 'window' into snum
sl@0
   233
	 * This is the part that corresponds to the current
sl@0
   234
	 * 'area' being divided */
sl@0
   235
	wnum.neg   = 0;
sl@0
   236
	wnum.d     = &(snum->d[loop]);
sl@0
   237
	wnum.top   = div_n;
sl@0
   238
	/* only needed when BN_ucmp messes up the values between top and max */
sl@0
   239
	wnum.dmax  = snum->dmax - loop; /* so we don't step out of bounds */
sl@0
   240
sl@0
   241
	/* Get the top 2 words of sdiv */
sl@0
   242
	/* div_n=sdiv->top; */
sl@0
   243
	d0=sdiv->d[div_n-1];
sl@0
   244
	d1=(div_n == 1)?0:sdiv->d[div_n-2];
sl@0
   245
sl@0
   246
	/* pointer to the 'top' of snum */
sl@0
   247
	wnump= &(snum->d[num_n-1]);
sl@0
   248
sl@0
   249
	/* Setup to 'res' */
sl@0
   250
	res->neg= (num->neg^divisor->neg);
sl@0
   251
	if (!bn_wexpand(res,(loop+1))) goto err;
sl@0
   252
	res->top=loop;
sl@0
   253
	resp= &(res->d[loop-1]);
sl@0
   254
sl@0
   255
	/* space for temp */
sl@0
   256
	if (!bn_wexpand(tmp,(div_n+1))) goto err;
sl@0
   257
sl@0
   258
	if (BN_ucmp(&wnum,sdiv) >= 0)
sl@0
   259
		{
sl@0
   260
		/* If BN_DEBUG_RAND is defined BN_ucmp changes (via
sl@0
   261
		 * bn_pollute) the const bignum arguments =>
sl@0
   262
		 * clean the values between top and max again */
sl@0
   263
		bn_clear_top2max(&wnum);
sl@0
   264
		bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n);
sl@0
   265
		*resp=1;
sl@0
   266
		}
sl@0
   267
	else
sl@0
   268
		res->top--;
sl@0
   269
	/* if res->top == 0 then clear the neg value otherwise decrease
sl@0
   270
	 * the resp pointer */
sl@0
   271
	if (res->top == 0)
sl@0
   272
		res->neg = 0;
sl@0
   273
	else
sl@0
   274
		resp--;
sl@0
   275
sl@0
   276
	for (i=0; i<loop-1; i++, wnump--, resp--)
sl@0
   277
		{
sl@0
   278
		BN_ULONG q,l0;
sl@0
   279
		/* the first part of the loop uses the top two words of
sl@0
   280
		 * snum and sdiv to calculate a BN_ULONG q such that
sl@0
   281
		 * | wnum - sdiv * q | < sdiv */
sl@0
   282
#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
sl@0
   283
		BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG);
sl@0
   284
		q=bn_div_3_words(wnump,d1,d0);
sl@0
   285
#else
sl@0
   286
		BN_ULONG n0,n1,rem=0;
sl@0
   287
sl@0
   288
		n0=wnump[0];
sl@0
   289
		n1=wnump[-1];
sl@0
   290
		if (n0 == d0)
sl@0
   291
			q=BN_MASK2;
sl@0
   292
		else 			/* n0 < d0 */
sl@0
   293
			{
sl@0
   294
#ifdef BN_LLONG
sl@0
   295
			BN_ULLONG t2;
sl@0
   296
sl@0
   297
#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
sl@0
   298
			q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0);
sl@0
   299
#else
sl@0
   300
			q=bn_div_words(n0,n1,d0);
sl@0
   301
#ifdef BN_DEBUG_LEVITTE
sl@0
   302
			fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
sl@0
   303
X) -> 0x%08X\n",
sl@0
   304
				n0, n1, d0, q);
sl@0
   305
#endif
sl@0
   306
#endif
sl@0
   307
sl@0
   308
#ifndef REMAINDER_IS_ALREADY_CALCULATED
sl@0
   309
			/*
sl@0
   310
			 * rem doesn't have to be BN_ULLONG. The least we
sl@0
   311
			 * know it's less that d0, isn't it?
sl@0
   312
			 */
sl@0
   313
			rem=(n1-q*d0)&BN_MASK2;
sl@0
   314
#endif
sl@0
   315
			t2=(BN_ULLONG)d1*q;
sl@0
   316
sl@0
   317
			for (;;)
sl@0
   318
				{
sl@0
   319
				if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2]))
sl@0
   320
					break;
sl@0
   321
				q--;
sl@0
   322
				rem += d0;
sl@0
   323
				if (rem < d0) break; /* don't let rem overflow */
sl@0
   324
				t2 -= d1;
sl@0
   325
				}
sl@0
   326
#else /* !BN_LLONG */
sl@0
   327
			BN_ULONG t2l,t2h,ql,qh;
sl@0
   328
sl@0
   329
			q=bn_div_words(n0,n1,d0);
sl@0
   330
#ifdef BN_DEBUG_LEVITTE
sl@0
   331
			fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
sl@0
   332
X) -> 0x%08X\n",
sl@0
   333
				n0, n1, d0, q);
sl@0
   334
#endif
sl@0
   335
#ifndef REMAINDER_IS_ALREADY_CALCULATED
sl@0
   336
			rem=(n1-q*d0)&BN_MASK2;
sl@0
   337
#endif
sl@0
   338
sl@0
   339
#if defined(BN_UMULT_LOHI)
sl@0
   340
			BN_UMULT_LOHI(t2l,t2h,d1,q);
sl@0
   341
#elif defined(BN_UMULT_HIGH)
sl@0
   342
			t2l = d1 * q;
sl@0
   343
			t2h = BN_UMULT_HIGH(d1,q);
sl@0
   344
#else
sl@0
   345
			t2l=LBITS(d1); t2h=HBITS(d1);
sl@0
   346
			ql =LBITS(q);  qh =HBITS(q);
sl@0
   347
			mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */
sl@0
   348
#endif
sl@0
   349
sl@0
   350
			for (;;)
sl@0
   351
				{
sl@0
   352
				if ((t2h < rem) ||
sl@0
   353
					((t2h == rem) && (t2l <= wnump[-2])))
sl@0
   354
					break;
sl@0
   355
				q--;
sl@0
   356
				rem += d0;
sl@0
   357
				if (rem < d0) break; /* don't let rem overflow */
sl@0
   358
				if (t2l < d1) t2h--; t2l -= d1;
sl@0
   359
				}
sl@0
   360
#endif /* !BN_LLONG */
sl@0
   361
			}
sl@0
   362
#endif /* !BN_DIV3W */
sl@0
   363
sl@0
   364
		l0=bn_mul_words(tmp->d,sdiv->d,div_n,q);
sl@0
   365
		tmp->d[div_n]=l0;
sl@0
   366
		wnum.d--;
sl@0
   367
		/* ingore top values of the bignums just sub the two 
sl@0
   368
		 * BN_ULONG arrays with bn_sub_words */
sl@0
   369
		if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n+1))
sl@0
   370
			{
sl@0
   371
			/* Note: As we have considered only the leading
sl@0
   372
			 * two BN_ULONGs in the calculation of q, sdiv * q
sl@0
   373
			 * might be greater than wnum (but then (q-1) * sdiv
sl@0
   374
			 * is less or equal than wnum)
sl@0
   375
			 */
sl@0
   376
			q--;
sl@0
   377
			if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n))
sl@0
   378
				/* we can't have an overflow here (assuming
sl@0
   379
				 * that q != 0, but if q == 0 then tmp is
sl@0
   380
				 * zero anyway) */
sl@0
   381
				(*wnump)++;
sl@0
   382
			}
sl@0
   383
		/* store part of the result */
sl@0
   384
		*resp = q;
sl@0
   385
		}
sl@0
   386
	bn_correct_top(snum);
sl@0
   387
	if (rm != NULL)
sl@0
   388
		{
sl@0
   389
		/* Keep a copy of the neg flag in num because if rm==num
sl@0
   390
		 * BN_rshift() will overwrite it.
sl@0
   391
		 */
sl@0
   392
		int neg = num->neg;
sl@0
   393
		BN_rshift(rm,snum,norm_shift);
sl@0
   394
		if (!BN_is_zero(rm))
sl@0
   395
			rm->neg = neg;
sl@0
   396
		bn_check_top(rm);
sl@0
   397
		}
sl@0
   398
	BN_CTX_end(ctx);
sl@0
   399
	return(1);
sl@0
   400
err:
sl@0
   401
	bn_check_top(rm);
sl@0
   402
	BN_CTX_end(ctx);
sl@0
   403
	return(0);
sl@0
   404
	}
sl@0
   405
sl@0
   406
/* BN_div_no_branch is a special version of BN_div. It does not contain
sl@0
   407
 * branches that may leak sensitive information.
sl@0
   408
 */
sl@0
   409
static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, 
sl@0
   410
	const BIGNUM *divisor, BN_CTX *ctx)
sl@0
   411
	{
sl@0
   412
	int norm_shift,i,loop;
sl@0
   413
	BIGNUM *tmp,wnum,*snum,*sdiv,*res;
sl@0
   414
	BN_ULONG *resp,*wnump;
sl@0
   415
	BN_ULONG d0,d1;
sl@0
   416
	int num_n,div_n;
sl@0
   417
sl@0
   418
	bn_check_top(dv);
sl@0
   419
	bn_check_top(rm);
sl@0
   420
	bn_check_top(num);
sl@0
   421
	bn_check_top(divisor);
sl@0
   422
sl@0
   423
	if (BN_is_zero(divisor))
sl@0
   424
		{
sl@0
   425
		BNerr(BN_F_BN_DIV_NO_BRANCH,BN_R_DIV_BY_ZERO);
sl@0
   426
		return(0);
sl@0
   427
		}
sl@0
   428
sl@0
   429
	BN_CTX_start(ctx);
sl@0
   430
	tmp=BN_CTX_get(ctx);
sl@0
   431
	snum=BN_CTX_get(ctx);
sl@0
   432
	sdiv=BN_CTX_get(ctx);
sl@0
   433
	if (dv == NULL)
sl@0
   434
		res=BN_CTX_get(ctx);
sl@0
   435
	else	res=dv;
sl@0
   436
	if (sdiv == NULL || res == NULL) goto err;
sl@0
   437
sl@0
   438
	/* First we normalise the numbers */
sl@0
   439
	norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2);
sl@0
   440
	if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err;
sl@0
   441
	sdiv->neg=0;
sl@0
   442
	norm_shift+=BN_BITS2;
sl@0
   443
	if (!(BN_lshift(snum,num,norm_shift))) goto err;
sl@0
   444
	snum->neg=0;
sl@0
   445
sl@0
   446
	/* Since we don't know whether snum is larger than sdiv,
sl@0
   447
	 * we pad snum with enough zeroes without changing its
sl@0
   448
	 * value. 
sl@0
   449
	 */
sl@0
   450
	if (snum->top <= sdiv->top+1) 
sl@0
   451
		{
sl@0
   452
		if (bn_wexpand(snum, sdiv->top + 2) == NULL) goto err;
sl@0
   453
		for (i = snum->top; i < sdiv->top + 2; i++) snum->d[i] = 0;
sl@0
   454
		snum->top = sdiv->top + 2;
sl@0
   455
		}
sl@0
   456
	else
sl@0
   457
		{
sl@0
   458
		if (bn_wexpand(snum, snum->top + 1) == NULL) goto err;
sl@0
   459
		snum->d[snum->top] = 0;
sl@0
   460
		snum->top ++;
sl@0
   461
		}
sl@0
   462
sl@0
   463
	div_n=sdiv->top;
sl@0
   464
	num_n=snum->top;
sl@0
   465
	loop=num_n-div_n;
sl@0
   466
	/* Lets setup a 'window' into snum
sl@0
   467
	 * This is the part that corresponds to the current
sl@0
   468
	 * 'area' being divided */
sl@0
   469
	wnum.neg   = 0;
sl@0
   470
	wnum.d     = &(snum->d[loop]);
sl@0
   471
	wnum.top   = div_n;
sl@0
   472
	/* only needed when BN_ucmp messes up the values between top and max */
sl@0
   473
	wnum.dmax  = snum->dmax - loop; /* so we don't step out of bounds */
sl@0
   474
sl@0
   475
	/* Get the top 2 words of sdiv */
sl@0
   476
	/* div_n=sdiv->top; */
sl@0
   477
	d0=sdiv->d[div_n-1];
sl@0
   478
	d1=(div_n == 1)?0:sdiv->d[div_n-2];
sl@0
   479
sl@0
   480
	/* pointer to the 'top' of snum */
sl@0
   481
	wnump= &(snum->d[num_n-1]);
sl@0
   482
sl@0
   483
	/* Setup to 'res' */
sl@0
   484
	res->neg= (num->neg^divisor->neg);
sl@0
   485
	if (!bn_wexpand(res,(loop+1))) goto err;
sl@0
   486
	res->top=loop-1;
sl@0
   487
	resp= &(res->d[loop-1]);
sl@0
   488
sl@0
   489
	/* space for temp */
sl@0
   490
	if (!bn_wexpand(tmp,(div_n+1))) goto err;
sl@0
   491
sl@0
   492
	/* if res->top == 0 then clear the neg value otherwise decrease
sl@0
   493
	 * the resp pointer */
sl@0
   494
	if (res->top == 0)
sl@0
   495
		res->neg = 0;
sl@0
   496
	else
sl@0
   497
		resp--;
sl@0
   498
sl@0
   499
	for (i=0; i<loop-1; i++, wnump--, resp--)
sl@0
   500
		{
sl@0
   501
		BN_ULONG q,l0;
sl@0
   502
		/* the first part of the loop uses the top two words of
sl@0
   503
		 * snum and sdiv to calculate a BN_ULONG q such that
sl@0
   504
		 * | wnum - sdiv * q | < sdiv */
sl@0
   505
#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
sl@0
   506
		BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG);
sl@0
   507
		q=bn_div_3_words(wnump,d1,d0);
sl@0
   508
#else
sl@0
   509
		BN_ULONG n0,n1,rem=0;
sl@0
   510
sl@0
   511
		n0=wnump[0];
sl@0
   512
		n1=wnump[-1];
sl@0
   513
		if (n0 == d0)
sl@0
   514
			q=BN_MASK2;
sl@0
   515
		else 			/* n0 < d0 */
sl@0
   516
			{
sl@0
   517
#ifdef BN_LLONG
sl@0
   518
			BN_ULLONG t2;
sl@0
   519
sl@0
   520
#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
sl@0
   521
			q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0);
sl@0
   522
#else
sl@0
   523
			q=bn_div_words(n0,n1,d0);
sl@0
   524
#ifdef BN_DEBUG_LEVITTE
sl@0
   525
			fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
sl@0
   526
X) -> 0x%08X\n",
sl@0
   527
				n0, n1, d0, q);
sl@0
   528
#endif
sl@0
   529
#endif
sl@0
   530
sl@0
   531
#ifndef REMAINDER_IS_ALREADY_CALCULATED
sl@0
   532
			/*
sl@0
   533
			 * rem doesn't have to be BN_ULLONG. The least we
sl@0
   534
			 * know it's less that d0, isn't it?
sl@0
   535
			 */
sl@0
   536
			rem=(n1-q*d0)&BN_MASK2;
sl@0
   537
#endif
sl@0
   538
			t2=(BN_ULLONG)d1*q;
sl@0
   539
sl@0
   540
			for (;;)
sl@0
   541
				{
sl@0
   542
				if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2]))
sl@0
   543
					break;
sl@0
   544
				q--;
sl@0
   545
				rem += d0;
sl@0
   546
				if (rem < d0) break; /* don't let rem overflow */
sl@0
   547
				t2 -= d1;
sl@0
   548
				}
sl@0
   549
#else /* !BN_LLONG */
sl@0
   550
			BN_ULONG t2l,t2h,ql,qh;
sl@0
   551
sl@0
   552
			q=bn_div_words(n0,n1,d0);
sl@0
   553
#ifdef BN_DEBUG_LEVITTE
sl@0
   554
			fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
sl@0
   555
X) -> 0x%08X\n",
sl@0
   556
				n0, n1, d0, q);
sl@0
   557
#endif
sl@0
   558
#ifndef REMAINDER_IS_ALREADY_CALCULATED
sl@0
   559
			rem=(n1-q*d0)&BN_MASK2;
sl@0
   560
#endif
sl@0
   561
sl@0
   562
#if defined(BN_UMULT_LOHI)
sl@0
   563
			BN_UMULT_LOHI(t2l,t2h,d1,q);
sl@0
   564
#elif defined(BN_UMULT_HIGH)
sl@0
   565
			t2l = d1 * q;
sl@0
   566
			t2h = BN_UMULT_HIGH(d1,q);
sl@0
   567
#else
sl@0
   568
			t2l=LBITS(d1); t2h=HBITS(d1);
sl@0
   569
			ql =LBITS(q);  qh =HBITS(q);
sl@0
   570
			mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */
sl@0
   571
#endif
sl@0
   572
sl@0
   573
			for (;;)
sl@0
   574
				{
sl@0
   575
				if ((t2h < rem) ||
sl@0
   576
					((t2h == rem) && (t2l <= wnump[-2])))
sl@0
   577
					break;
sl@0
   578
				q--;
sl@0
   579
				rem += d0;
sl@0
   580
				if (rem < d0) break; /* don't let rem overflow */
sl@0
   581
				if (t2l < d1) t2h--; t2l -= d1;
sl@0
   582
				}
sl@0
   583
#endif /* !BN_LLONG */
sl@0
   584
			}
sl@0
   585
#endif /* !BN_DIV3W */
sl@0
   586
sl@0
   587
		l0=bn_mul_words(tmp->d,sdiv->d,div_n,q);
sl@0
   588
		tmp->d[div_n]=l0;
sl@0
   589
		wnum.d--;
sl@0
   590
		/* ingore top values of the bignums just sub the two 
sl@0
   591
		 * BN_ULONG arrays with bn_sub_words */
sl@0
   592
		if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n+1))
sl@0
   593
			{
sl@0
   594
			/* Note: As we have considered only the leading
sl@0
   595
			 * two BN_ULONGs in the calculation of q, sdiv * q
sl@0
   596
			 * might be greater than wnum (but then (q-1) * sdiv
sl@0
   597
			 * is less or equal than wnum)
sl@0
   598
			 */
sl@0
   599
			q--;
sl@0
   600
			if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n))
sl@0
   601
				/* we can't have an overflow here (assuming
sl@0
   602
				 * that q != 0, but if q == 0 then tmp is
sl@0
   603
				 * zero anyway) */
sl@0
   604
				(*wnump)++;
sl@0
   605
			}
sl@0
   606
		/* store part of the result */
sl@0
   607
		*resp = q;
sl@0
   608
		}
sl@0
   609
	bn_correct_top(snum);
sl@0
   610
	if (rm != NULL)
sl@0
   611
		{
sl@0
   612
		/* Keep a copy of the neg flag in num because if rm==num
sl@0
   613
		 * BN_rshift() will overwrite it.
sl@0
   614
		 */
sl@0
   615
		int neg = num->neg;
sl@0
   616
		BN_rshift(rm,snum,norm_shift);
sl@0
   617
		if (!BN_is_zero(rm))
sl@0
   618
			rm->neg = neg;
sl@0
   619
		bn_check_top(rm);
sl@0
   620
		}
sl@0
   621
	bn_correct_top(res);
sl@0
   622
	BN_CTX_end(ctx);
sl@0
   623
	return(1);
sl@0
   624
err:
sl@0
   625
	bn_check_top(rm);
sl@0
   626
	BN_CTX_end(ctx);
sl@0
   627
	return(0);
sl@0
   628
	}
sl@0
   629
sl@0
   630
#endif