Ensure that no-comp functions are flagged as such
[openssl.git] / crypto / bn / bn_sqr.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 "internal/cryptlib.h"
59 #include "bn_lcl.h"
60
61 /* r must not be a */
62 /*
63  * I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96
64  */
65 int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
66 {
67     int max, al;
68     int ret = 0;
69     BIGNUM *tmp, *rr;
70
71     bn_check_top(a);
72
73     al = a->top;
74     if (al <= 0) {
75         r->top = 0;
76         r->neg = 0;
77         return 1;
78     }
79
80     BN_CTX_start(ctx);
81     rr = (a != r) ? r : BN_CTX_get(ctx);
82     tmp = BN_CTX_get(ctx);
83     if (!rr || !tmp)
84         goto err;
85
86     max = 2 * al;               /* Non-zero (from above) */
87     if (bn_wexpand(rr, max) == NULL)
88         goto err;
89
90     if (al == 4) {
91 #ifndef BN_SQR_COMBA
92         BN_ULONG t[8];
93         bn_sqr_normal(rr->d, a->d, 4, t);
94 #else
95         bn_sqr_comba4(rr->d, a->d);
96 #endif
97     } else if (al == 8) {
98 #ifndef BN_SQR_COMBA
99         BN_ULONG t[16];
100         bn_sqr_normal(rr->d, a->d, 8, t);
101 #else
102         bn_sqr_comba8(rr->d, a->d);
103 #endif
104     } else {
105 #if defined(BN_RECURSION)
106         if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) {
107             BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL * 2];
108             bn_sqr_normal(rr->d, a->d, al, t);
109         } else {
110             int j, k;
111
112             j = BN_num_bits_word((BN_ULONG)al);
113             j = 1 << (j - 1);
114             k = j + j;
115             if (al == j) {
116                 if (bn_wexpand(tmp, k * 2) == NULL)
117                     goto err;
118                 bn_sqr_recursive(rr->d, a->d, al, tmp->d);
119             } else {
120                 if (bn_wexpand(tmp, max) == NULL)
121                     goto err;
122                 bn_sqr_normal(rr->d, a->d, al, tmp->d);
123             }
124         }
125 #else
126         if (bn_wexpand(tmp, max) == NULL)
127             goto err;
128         bn_sqr_normal(rr->d, a->d, al, tmp->d);
129 #endif
130     }
131
132     rr->neg = 0;
133     /*
134      * If the most-significant half of the top word of 'a' is zero, then the
135      * square of 'a' will max-1 words.
136      */
137     if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l))
138         rr->top = max - 1;
139     else
140         rr->top = max;
141     if (rr != r)
142         BN_copy(r, rr);
143     ret = 1;
144  err:
145     bn_check_top(rr);
146     bn_check_top(tmp);
147     BN_CTX_end(ctx);
148     return (ret);
149 }
150
151 /* tmp must have 2*n words */
152 void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp)
153 {
154     int i, j, max;
155     const BN_ULONG *ap;
156     BN_ULONG *rp;
157
158     max = n * 2;
159     ap = a;
160     rp = r;
161     rp[0] = rp[max - 1] = 0;
162     rp++;
163     j = n;
164
165     if (--j > 0) {
166         ap++;
167         rp[j] = bn_mul_words(rp, ap, j, ap[-1]);
168         rp += 2;
169     }
170
171     for (i = n - 2; i > 0; i--) {
172         j--;
173         ap++;
174         rp[j] = bn_mul_add_words(rp, ap, j, ap[-1]);
175         rp += 2;
176     }
177
178     bn_add_words(r, r, r, max);
179
180     /* There will not be a carry */
181
182     bn_sqr_words(tmp, a, n);
183
184     bn_add_words(r, r, tmp, max);
185 }
186
187 #ifdef BN_RECURSION
188 /*-
189  * r is 2*n words in size,
190  * a and b are both n words in size.    (There's not actually a 'b' here ...)
191  * n must be a power of 2.
192  * We multiply and return the result.
193  * t must be 2*n words in size
194  * We calculate
195  * a[0]*b[0]
196  * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
197  * a[1]*b[1]
198  */
199 void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t)
200 {
201     int n = n2 / 2;
202     int zero, c1;
203     BN_ULONG ln, lo, *p;
204
205     if (n2 == 4) {
206 # ifndef BN_SQR_COMBA
207         bn_sqr_normal(r, a, 4, t);
208 # else
209         bn_sqr_comba4(r, a);
210 # endif
211         return;
212     } else if (n2 == 8) {
213 # ifndef BN_SQR_COMBA
214         bn_sqr_normal(r, a, 8, t);
215 # else
216         bn_sqr_comba8(r, a);
217 # endif
218         return;
219     }
220     if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) {
221         bn_sqr_normal(r, a, n2, t);
222         return;
223     }
224     /* r=(a[0]-a[1])*(a[1]-a[0]) */
225     c1 = bn_cmp_words(a, &(a[n]), n);
226     zero = 0;
227     if (c1 > 0)
228         bn_sub_words(t, a, &(a[n]), n);
229     else if (c1 < 0)
230         bn_sub_words(t, &(a[n]), a, n);
231     else
232         zero = 1;
233
234     /* The result will always be negative unless it is zero */
235     p = &(t[n2 * 2]);
236
237     if (!zero)
238         bn_sqr_recursive(&(t[n2]), t, n, p);
239     else
240         memset(&t[n2], 0, sizeof(*t) * n2);
241     bn_sqr_recursive(r, a, n, p);
242     bn_sqr_recursive(&(r[n2]), &(a[n]), n, p);
243
244     /*-
245      * t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero
246      * r[10] holds (a[0]*b[0])
247      * r[32] holds (b[1]*b[1])
248      */
249
250     c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
251
252     /* t[32] is negative */
253     c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
254
255     /*-
256      * t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1])
257      * r[10] holds (a[0]*a[0])
258      * r[32] holds (a[1]*a[1])
259      * c1 holds the carry bits
260      */
261     c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
262     if (c1) {
263         p = &(r[n + n2]);
264         lo = *p;
265         ln = (lo + c1) & BN_MASK2;
266         *p = ln;
267
268         /*
269          * The overflow will stop before we over write words we should not
270          * overwrite
271          */
272         if (ln < (BN_ULONG)c1) {
273             do {
274                 p++;
275                 lo = *p;
276                 ln = (lo + 1) & BN_MASK2;
277                 *p = ln;
278             } while (ln == 0);
279         }
280     }
281 }
282 #endif