~ubuntu-branches/ubuntu/hardy/openssl/hardy-security

« back to all changes in this revision

Viewing changes to crypto/bn/bn_div.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2005-12-13 21:37:42 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051213213742-7em5nrw5c7ceegyd
Tags: 0.9.8a-5
Stop ssh from crashing randomly on sparc (Closes: #335912)
Patch from upstream cvs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
179
179
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
180
180
           BN_CTX *ctx)
181
181
        {
182
 
        int norm_shift,i,j,loop;
 
182
        int norm_shift,i,loop;
183
183
        BIGNUM *tmp,wnum,*snum,*sdiv,*res;
184
184
        BN_ULONG *resp,*wnump;
185
185
        BN_ULONG d0,d1;
186
186
        int num_n,div_n;
187
187
 
 
188
        bn_check_top(dv);
 
189
        bn_check_top(rm);
188
190
        bn_check_top(num);
189
191
        bn_check_top(divisor);
190
192
 
210
212
                res=BN_CTX_get(ctx);
211
213
        else    res=dv;
212
214
        if (sdiv == NULL || res == NULL) goto err;
213
 
        tmp->neg=0;
214
215
 
215
216
        /* First we normalise the numbers */
216
217
        norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2);
222
223
        div_n=sdiv->top;
223
224
        num_n=snum->top;
224
225
        loop=num_n-div_n;
225
 
 
226
226
        /* Lets setup a 'window' into snum
227
227
         * This is the part that corresponds to the current
228
228
         * 'area' being divided */
229
 
        BN_init(&wnum);
230
 
        wnum.d=  &(snum->d[loop]);
231
 
        wnum.top= div_n;
232
 
        wnum.dmax= snum->dmax+1; /* a bit of a lie */
 
229
        wnum.neg   = 0;
 
230
        wnum.d     = &(snum->d[loop]);
 
231
        wnum.top   = div_n;
 
232
        /* only needed when BN_ucmp messes up the values between top and max */
 
233
        wnum.dmax  = snum->dmax - loop; /* so we don't step out of bounds */
233
234
 
234
235
        /* Get the top 2 words of sdiv */
235
 
        /* i=sdiv->top; */
 
236
        /* div_n=sdiv->top; */
236
237
        d0=sdiv->d[div_n-1];
237
238
        d1=(div_n == 1)?0:sdiv->d[div_n-2];
238
239
 
250
251
 
251
252
        if (BN_ucmp(&wnum,sdiv) >= 0)
252
253
                {
253
 
                if (!BN_usub(&wnum,&wnum,sdiv)) goto err;
 
254
                /* If BN_DEBUG_RAND is defined BN_ucmp changes (via
 
255
                 * bn_pollute) the const bignum arguments =>
 
256
                 * clean the values between top and max again */
 
257
                bn_clear_top2max(&wnum);
 
258
                bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n);
254
259
                *resp=1;
255
 
                res->d[res->top-1]=1;
256
260
                }
257
261
        else
258
262
                res->top--;
 
263
        /* if res->top == 0 then clear the neg value otherwise decrease
 
264
         * the resp pointer */
259
265
        if (res->top == 0)
260
266
                res->neg = 0;
261
 
        resp--;
 
267
        else
 
268
                resp--;
262
269
 
263
 
        for (i=0; i<loop-1; i++)
 
270
        for (i=0; i<loop-1; i++, wnump--, resp--)
264
271
                {
265
272
                BN_ULONG q,l0;
 
273
                /* the first part of the loop uses the top two words of
 
274
                 * snum and sdiv to calculate a BN_ULONG q such that
 
275
                 * | wnum - sdiv * q | < sdiv */
266
276
#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
267
277
                BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG);
268
278
                q=bn_div_3_words(wnump,d1,d0);
346
356
#endif /* !BN_DIV3W */
347
357
 
348
358
                l0=bn_mul_words(tmp->d,sdiv->d,div_n,q);
349
 
                wnum.d--; wnum.top++;
350
359
                tmp->d[div_n]=l0;
351
 
                for (j=div_n+1; j>0; j--)
352
 
                        if (tmp->d[j-1]) break;
353
 
                tmp->top=j;
354
 
 
355
 
                j=wnum.top;
356
 
                if (!BN_sub(&wnum,&wnum,tmp)) goto err;
357
 
 
358
 
                snum->top=snum->top+wnum.top-j;
359
 
 
360
 
                if (wnum.neg)
 
360
                wnum.d--;
 
361
                /* ingore top values of the bignums just sub the two 
 
362
                 * BN_ULONG arrays with bn_sub_words */
 
363
                if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n+1))
361
364
                        {
 
365
                        /* Note: As we have considered only the leading
 
366
                         * two BN_ULONGs in the calculation of q, sdiv * q
 
367
                         * might be greater than wnum (but then (q-1) * sdiv
 
368
                         * is less or equal than wnum)
 
369
                         */
362
370
                        q--;
363
 
                        j=wnum.top;
364
 
                        if (!BN_add(&wnum,&wnum,sdiv)) goto err;
365
 
                        snum->top+=wnum.top-j;
 
371
                        if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n))
 
372
                                /* we can't have an overflow here (assuming
 
373
                                 * that q != 0, but if q == 0 then tmp is
 
374
                                 * zero anyway) */
 
375
                                (*wnump)++;
366
376
                        }
367
 
                *(resp--)=q;
368
 
                wnump--;
 
377
                /* store part of the result */
 
378
                *resp = q;
369
379
                }
 
380
        bn_correct_top(snum);
370
381
        if (rm != NULL)
371
382
                {
372
383
                /* Keep a copy of the neg flag in num because if rm==num
376
387
                BN_rshift(rm,snum,norm_shift);
377
388
                if (!BN_is_zero(rm))
378
389
                        rm->neg = neg;
 
390
                bn_check_top(rm);
379
391
                }
380
392
        BN_CTX_end(ctx);
381
393
        return(1);
382
394
err:
 
395
        bn_check_top(rm);
383
396
        BN_CTX_end(ctx);
384
397
        return(0);
385
398
        }