Import of old SSLeay release: SSLeay 0.8.1b
[openssl.git] / crypto / bn / bn_mulw.c
1 /* crypto/bn/bn_mulw.c */
2 /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include "bn_lcl.h"
62
63 #ifdef BN_LLONG 
64
65 BN_ULONG bn_mul_add_word(rp,ap,num,w)
66 BN_ULONG *rp,*ap;
67 int num;
68 BN_ULONG w;
69         {
70         BN_ULONG c1=0;
71
72         for (;;)
73                 {
74                 mul_add(rp[0],ap[0],w,c1);
75                 if (--num == 0) break;
76                 mul_add(rp[1],ap[1],w,c1);
77                 if (--num == 0) break;
78                 mul_add(rp[2],ap[2],w,c1);
79                 if (--num == 0) break;
80                 mul_add(rp[3],ap[3],w,c1);
81                 if (--num == 0) break;
82                 ap+=4;
83                 rp+=4;
84                 }
85         
86         return(c1);
87         } 
88
89 BN_ULONG bn_mul_word(rp,ap,num,w)
90 BN_ULONG *rp,*ap;
91 int num;
92 BN_ULONG w;
93         {
94         BN_ULONG c1=0;
95
96         for (;;)
97                 {
98                 mul(rp[0],ap[0],w,c1);
99                 if (--num == 0) break;
100                 mul(rp[1],ap[1],w,c1);
101                 if (--num == 0) break;
102                 mul(rp[2],ap[2],w,c1);
103                 if (--num == 0) break;
104                 mul(rp[3],ap[3],w,c1);
105                 if (--num == 0) break;
106                 ap+=4;
107                 rp+=4;
108                 }
109         return(c1);
110         } 
111
112 void bn_sqr_words(r,a,n)
113 BN_ULONG *r,*a;
114 int n;
115         {
116         for (;;)
117                 {
118                 BN_ULLONG t;
119
120                 t=(BN_ULLONG)(a[0])*(a[0]);
121                 r[0]=Lw(t); r[1]=Hw(t);
122                 if (--n == 0) break;
123
124                 t=(BN_ULLONG)(a[1])*(a[1]);
125                 r[2]=Lw(t); r[3]=Hw(t);
126                 if (--n == 0) break;
127
128                 t=(BN_ULLONG)(a[2])*(a[2]);
129                 r[4]=Lw(t); r[5]=Hw(t);
130                 if (--n == 0) break;
131
132                 t=(BN_ULLONG)(a[3])*(a[3]);
133                 r[6]=Lw(t); r[7]=Hw(t);
134                 if (--n == 0) break;
135
136                 a+=4;
137                 r+=8;
138                 }
139         }
140
141 #else
142
143 BN_ULONG bn_mul_add_word(rp,ap,num,w)
144 BN_ULONG *rp,*ap;
145 int num;
146 BN_ULONG w;
147         {
148         BN_ULONG c=0;
149         BN_ULONG bl,bh;
150
151         bl=LBITS(w);
152         bh=HBITS(w);
153
154         for (;;)
155                 {
156                 mul_add(rp[0],ap[0],bl,bh,c);
157                 if (--num == 0) break;
158                 mul_add(rp[1],ap[1],bl,bh,c);
159                 if (--num == 0) break;
160                 mul_add(rp[2],ap[2],bl,bh,c);
161                 if (--num == 0) break;
162                 mul_add(rp[3],ap[3],bl,bh,c);
163                 if (--num == 0) break;
164                 ap+=4;
165                 rp+=4;
166                 }
167         return(c);
168         } 
169
170 BN_ULONG bn_mul_word(rp,ap,num,w)
171 BN_ULONG *rp,*ap;
172 int num;
173 BN_ULONG w;
174         {
175         BN_ULONG carry=0;
176         BN_ULONG bl,bh;
177
178         bl=LBITS(w);
179         bh=HBITS(w);
180
181         for (;;)
182                 {
183                 mul(rp[0],ap[0],bl,bh,carry);
184                 if (--num == 0) break;
185                 mul(rp[1],ap[1],bl,bh,carry);
186                 if (--num == 0) break;
187                 mul(rp[2],ap[2],bl,bh,carry);
188                 if (--num == 0) break;
189                 mul(rp[3],ap[3],bl,bh,carry);
190                 if (--num == 0) break;
191                 ap+=4;
192                 rp+=4;
193                 }
194         return(carry);
195         } 
196
197 void bn_sqr_words(r,a,n)
198 BN_ULONG *r,*a;
199 int n;
200         {
201         for (;;)
202                 {
203                 sqr64(r[0],r[1],a[0]);
204                 if (--n == 0) break;
205
206                 sqr64(r[2],r[3],a[1]);
207                 if (--n == 0) break;
208
209                 sqr64(r[4],r[5],a[2]);
210                 if (--n == 0) break;
211
212                 sqr64(r[6],r[7],a[3]);
213                 if (--n == 0) break;
214
215                 a+=4;
216                 r+=8;
217                 }
218         }
219
220 #endif
221
222 #if defined(BN_LLONG) && defined(BN_DIV2W)
223
224 BN_ULONG bn_div64(h,l,d)
225 BN_ULONG h,l,d;
226         {
227         return((BN_ULONG)(((((BN_ULLONG)h)<<BN_BITS2)|l)/(BN_ULLONG)d));
228         }
229
230 #else
231
232 /* Divide h-l by d and return the result. */
233 /* I need to test this some more :-( */
234 BN_ULONG bn_div64(h,l,d)
235 BN_ULONG h,l,d;
236         {
237         BN_ULONG dh,dl,q,ret=0,th,tl,t;
238         int i,count=2;
239
240         if (d == 0) return(BN_MASK2);
241
242         i=BN_num_bits_word(d);
243         if ((i != BN_BITS2) && (h > (BN_ULONG)1<<i))
244                 {
245 #ifndef WIN16
246                 fprintf(stderr,"Division would overflow (%d)\n",i);
247 #endif
248                 abort();
249                 }
250         i=BN_BITS2-i;
251         if (h >= d) h-=d;
252
253         if (i)
254                 {
255                 d<<=i;
256                 h=(h<<i)|(l>>(BN_BITS2-i));
257                 l<<=i;
258                 }
259         dh=(d&BN_MASK2h)>>BN_BITS4;
260         dl=(d&BN_MASK2l);
261         for (;;)
262                 {
263                 if ((h>>BN_BITS4) == dh)
264                         q=BN_MASK2l;
265                 else
266                         q=h/dh;
267
268                 for (;;)
269                         {
270                         t=(h-q*dh);
271                         if ((t&BN_MASK2h) ||
272                                 ((dl*q) <= (
273                                         (t<<BN_BITS4)+
274                                         ((l&BN_MASK2h)>>BN_BITS4))))
275                                 break;
276                         q--;
277                         }
278                 th=q*dh;
279                 tl=q*dl;
280                 t=(tl>>BN_BITS4);
281                 tl=(tl<<BN_BITS4)&BN_MASK2h;
282                 th+=t;
283
284                 if (l < tl) th++;
285                 l-=tl;
286                 if (h < th)
287                         {
288                         h+=d;
289                         q--;
290                         }
291                 h-=th;
292
293                 if (--count == 0) break;
294
295                 ret=q<<BN_BITS4;
296                 h=((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2;
297                 l=(l&BN_MASK2l)<<BN_BITS4;
298                 }
299         ret|=q;
300         return(ret);
301         }
302 #endif
303