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