faf0e347e24420b1123026aed04a3a79d74ea63c
[openssl.git] / crypto / bn / bn_nist.c
1 /* crypto/bn/bn_nist.c */
2 /*
3  * Written by Nils Larsch for the OpenSSL project
4  */
5 /* ====================================================================
6  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    openssl-core@openssl.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include "bn_lcl.h"
60 #include "cryptlib.h"
61
62 #define BN_NIST_192_TOP (192+BN_BITS2-1)/BN_BITS2
63 #define BN_NIST_224_TOP (224+BN_BITS2-1)/BN_BITS2
64 #define BN_NIST_256_TOP (256+BN_BITS2-1)/BN_BITS2
65 #define BN_NIST_384_TOP (384+BN_BITS2-1)/BN_BITS2
66 #define BN_NIST_521_TOP (521+BN_BITS2-1)/BN_BITS2
67
68 #if BN_BITS2 == 64
69 static const BN_ULONG _nist_p_192[] =
70         {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFEULL,
71         0xFFFFFFFFFFFFFFFFULL};
72 static const BN_ULONG _nist_p_224[] =
73         {0x0000000000000001ULL,0xFFFFFFFF00000000ULL,
74         0xFFFFFFFFFFFFFFFFULL,0x00000000FFFFFFFFULL};
75 static const BN_ULONG _nist_p_256[] =
76         {0xFFFFFFFFFFFFFFFFULL,0x00000000FFFFFFFFULL,
77         0x0000000000000000ULL,0xFFFFFFFF00000001ULL};
78 static const BN_ULONG _nist_p_384[] =
79         {0x00000000FFFFFFFFULL,0xFFFFFFFF00000000ULL,
80         0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFFULL,
81         0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL};
82 static const BN_ULONG _nist_p_521[] =
83         {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
84         0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
85         0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
86         0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
87         0x00000000000001FFULL};
88 #elif BN_BITS2 == 32
89 static const BN_ULONG _nist_p_192[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,
90         0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
91 static const BN_ULONG _nist_p_224[] = {0x00000001,0x00000000,0x00000000,
92         0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
93 static const BN_ULONG _nist_p_256[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
94         0x00000000,0x00000000,0x00000000,0x00000001,0xFFFFFFFF};
95 static const BN_ULONG _nist_p_384[] = {0xFFFFFFFF,0x00000000,0x00000000,
96         0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
97         0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
98 static const BN_ULONG _nist_p_521[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
99         0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
100         0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
101         0xFFFFFFFF,0x000001FF};
102 #elif BN_BITS2 == 16
103 static const BN_ULONG _nist_p_192[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFE,
104         0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
105 static const BN_ULONG _nist_p_224[] = {0x0001,0x0000,0x0000,0x0000,0x0000,
106         0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
107 static const BN_ULONG _nist_p_256[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
108         0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0x0000,0xFFFF,
109         0xFFFF};
110 static const BN_ULONG _nist_p_384[] = {0xFFFF,0xFFFF,0x0000,0x0000,0x0000,
111         0x0000,0xFFFF,0xFFFF,0xFFFE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
112         0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
113 static const BN_ULONG _nist_p_521[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
114         0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
115         0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
116         0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x01FF};
117 #elif BN_BITS2 == 8
118 static const BN_ULONG _nist_p_192[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
119         0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
120         0xFF,0xFF};
121 static const BN_ULONG _nist_p_224[] = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122         0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
123         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
124 static const BN_ULONG _nist_p_256[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
125         0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126         0x00,0x00,0x01,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF};
127 static const BN_ULONG _nist_p_384[] = {0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
128         0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
129         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
130         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
131 static const BN_ULONG _nist_p_521[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
132         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
133         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
134         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
135         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
136         0xFF,0x01};
137 #endif
138
139 const BIGNUM *BN_get0_nist_prime_192(void)
140         {
141         static BIGNUM const_nist_192 = { (BN_ULONG *)_nist_p_192,
142                 BN_NIST_192_TOP, BN_NIST_192_TOP, 0, BN_FLG_STATIC_DATA };
143         return &const_nist_192;
144         }
145
146 const BIGNUM *BN_get0_nist_prime_224(void)
147         {
148         static BIGNUM const_nist_224 = { (BN_ULONG *)_nist_p_224,
149                 BN_NIST_224_TOP, BN_NIST_224_TOP, 0, BN_FLG_STATIC_DATA };
150         return &const_nist_224;
151         }
152
153 const BIGNUM *BN_get0_nist_prime_256(void)
154         {
155         static BIGNUM const_nist_256 = { (BN_ULONG *)_nist_p_256,
156                 BN_NIST_256_TOP, BN_NIST_256_TOP, 0, BN_FLG_STATIC_DATA };
157         return &const_nist_256;
158         }
159
160 const BIGNUM *BN_get0_nist_prime_384(void)
161         {
162         static BIGNUM const_nist_384 = { (BN_ULONG *)_nist_p_384,
163                 BN_NIST_384_TOP, BN_NIST_384_TOP, 0, BN_FLG_STATIC_DATA };
164         return &const_nist_384;
165         }
166
167 const BIGNUM *BN_get0_nist_prime_521(void)
168         {
169         static BIGNUM const_nist_521 = { (BN_ULONG *)_nist_p_521,
170                 BN_NIST_521_TOP, BN_NIST_521_TOP, 0, BN_FLG_STATIC_DATA };
171         return &const_nist_521;
172         }
173
174 /* some misc internal functions */
175 static BN_ULONG _256_data[BN_NIST_256_TOP*6];
176 static int _is_set_256_data = 0;
177 static void _init_256_data(void);
178
179 static BN_ULONG _384_data[BN_NIST_384_TOP*8];
180 static int _is_set_384_data = 0;
181 static void _init_384_data(void);
182
183 #define BN_NIST_ADD_ONE(a)      while (!(++(*(a)))) ++(a);
184
185 static void nist_cp_bn_0(BN_ULONG *buf, BN_ULONG *a, int top, int max)
186         {
187         int i;
188         BN_ULONG *_tmp1 = (buf), *_tmp2 = (a);
189         for (i = (top); i != 0; i--)
190                 *_tmp1++ = *_tmp2++;
191         for (i = (max) - (top); i != 0; i--)
192                 *_tmp1++ = (BN_ULONG) 0;
193         }
194
195 static void nist_cp_bn(BN_ULONG *buf, BN_ULONG *a, int top)
196         { 
197         int i;
198         BN_ULONG *_tmp1 = (buf), *_tmp2 = (a);
199         for (i = (top); i != 0; i--)
200                 *_tmp1++ = *_tmp2++;
201         }
202
203 #if BN_BITS2 == 64
204 #define bn_cp_64(to, n, from, m)        (to)[n] = (from)[m];
205 #define bn_64_set_0(to, n)              (to)[n] = (BN_ULONG)0;
206 /* TBD */
207 #define bn_cp_32(to, n, from, m)        (to)[n] = (from)[m];
208 #define bn_32_set_0(to, n)              (to)[n] = (BN_ULONG)0;
209 #else
210 #define bn_cp_64(to, n, from, m) \
211         { \
212         bn_cp_32(to, (n)*2, from, (m)*2); \
213         bn_cp_32(to, (n)*2+1, from, (m)*2+1); \
214         }
215 #define bn_64_set_0(to, n) \
216         { \
217         bn_32_set_0(to, (n)*2); \
218         bn_32_set_0(to, (n)*2+1); \
219         }
220 #if BN_BITS2 == 32
221 #define bn_cp_32(to, n, from, m)        (to)[n] = (from)[m];
222 #define bn_32_set_0(to, n)              (to)[n] = (BN_ULONG)0;
223 #elif BN_BITS2 == 16
224 #define bn_cp_32(to, n, from, m) \
225         { \
226         (to)[(n)*2]   = (from)[(m)*2];  \
227         (to)[(n)*2+1] = (from)[(m)*2+1];\
228         }
229 #define bn_32_set_0(to, n) { (to)[(n)*2] = 0; (to)[(n)*2+1] = 0; }
230 #elif BN_BITS2 == 8
231 #define bn_cp_32(to, n, from, m) \
232         { \
233         (to)[(n)*4]   = (from)[(m)*4];  \
234         (to)[(n)*4+1] = (from)[(m)*4+1];\
235         (to)[(n)*4+2] = (from)[(m)*4+2];\
236         (to)[(n)*4+3] = (from)[(m)*4+3];\
237         }
238 #define bn_32_set_0(to, n) \
239         { (to)[(n)*4]   = (BN_ULONG)0; (to)[(n)*4+1] = (BN_ULONG)0; \
240           (to)[(n)*4+2] = (BN_ULONG)0; (to)[(n)*4+3] = (BN_ULONG)0; }
241 #endif
242 #endif /* BN_BITS2 != 64 */
243
244
245 #define nist_set_192(to, from, a1, a2, a3) \
246         { \
247         if (a3 != 0) bn_cp_64(to, 0, from, (a3) - 3) else bn_64_set_0(to, 0)\
248         bn_cp_64(to, 1, from, (a2) - 3) \
249         if (a1 != 0) bn_cp_64(to, 2, from, (a1) - 3) else bn_64_set_0(to, 2)\
250         }
251
252 int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
253         BN_CTX *ctx)
254         {
255         int      top = a->top, i;
256         BN_ULONG carry = 0;
257         register BN_ULONG *r_d, *a_d = a->d;
258         BN_ULONG t_d[BN_NIST_192_TOP],
259                  buf[BN_NIST_192_TOP];
260
261         i = BN_ucmp(field, a);
262         if (i == 0)
263                 {
264                 BN_zero(r);
265                 return 1;
266                 }
267         else if (i > 0)
268                 return (r == a) ? 1 : (BN_copy(r ,a) != NULL);
269
270         if (top == BN_NIST_192_TOP)
271                 return BN_usub(r, a, field);
272
273         if (r != a)
274                 {
275                 if (!bn_wexpand(r, BN_NIST_192_TOP))
276                         return 0;
277                 r_d = r->d;
278                 nist_cp_bn(r_d, a_d, BN_NIST_192_TOP);
279                 }
280         else
281                 r_d = a_d;
282
283         nist_cp_bn_0(buf, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP, BN_NIST_192_TOP);
284
285 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
286 # pragma message save
287 # pragma message disable BADSUBSCRIPT
288 #endif
289
290         nist_set_192(t_d, buf, 0, 3, 3);
291         if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
292                 ++carry;
293
294         nist_set_192(t_d, buf, 4, 4, 0);
295         if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
296                 ++carry;
297
298 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
299 # pragma message restore
300 #endif
301
302         nist_set_192(t_d, buf, 5, 5, 5)
303         if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
304                 ++carry;
305
306         while (carry)
307                 {
308                 if (bn_sub_words(r_d, r_d, _nist_p_192, BN_NIST_192_TOP))
309                         --carry; 
310                 }
311         r->top = BN_NIST_192_TOP;
312         bn_correct_top(r);
313         if (BN_ucmp(r, field) >= 0)
314                 {
315                 bn_sub_words(r_d, r_d, _nist_p_192, BN_NIST_192_TOP);
316                 bn_correct_top(r);
317                 }
318
319         bn_check_top(r);
320         return 1;
321         }
322
323 #define nist_set_224(to, from, a1, a2, a3, a4, a5, a6, a7) \
324         { \
325         if (a7 != 0) bn_cp_32(to, 0, from, (a7) - 7) else bn_32_set_0(to, 0)\
326         if (a6 != 0) bn_cp_32(to, 1, from, (a6) - 7) else bn_32_set_0(to, 1)\
327         if (a5 != 0) bn_cp_32(to, 2, from, (a5) - 7) else bn_32_set_0(to, 2)\
328         if (a4 != 0) bn_cp_32(to, 3, from, (a4) - 7) else bn_32_set_0(to, 3)\
329         if (a3 != 0) bn_cp_32(to, 4, from, (a3) - 7) else bn_32_set_0(to, 4)\
330         if (a2 != 0) bn_cp_32(to, 5, from, (a2) - 7) else bn_32_set_0(to, 5)\
331         if (a1 != 0) bn_cp_32(to, 6, from, (a1) - 7) else bn_32_set_0(to, 6)\
332         }
333
334 int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
335         BN_CTX *ctx)
336         {
337 #if BN_BITS2 != 64
338         int     top = a->top, i;
339         int     carry = 0;
340         BN_ULONG *r_d, *a_d = a->d;
341         BN_ULONG t_d[BN_NIST_224_TOP],
342                  buf[BN_NIST_224_TOP];
343
344         i = BN_ucmp(field, a);
345         if (i == 0)
346                 {
347                 BN_zero(r);
348                 return 1;
349                 }
350         else if (i > 0)
351                 return (r == a)? 1 : (BN_copy(r ,a) != NULL);
352
353         if (top == BN_NIST_224_TOP)
354                 return BN_usub(r, a, field);
355
356         if (r != a)
357                 {
358                 if (!bn_wexpand(r, BN_NIST_224_TOP))
359                         return 0;
360                 r_d = r->d;
361                 nist_cp_bn(r_d, a_d, BN_NIST_224_TOP);
362                 }
363         else
364                 r_d = a_d;
365
366         nist_cp_bn_0(buf, a_d + BN_NIST_224_TOP, top - BN_NIST_224_TOP, BN_NIST_224_TOP);
367
368         nist_set_224(t_d, buf, 10, 9, 8, 7, 0, 0, 0);
369         if (bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP))
370                 ++carry;
371         nist_set_224(t_d, buf, 0, 13, 12, 11, 0, 0, 0);
372         if (bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP))
373                 ++carry;
374         nist_set_224(t_d, buf, 13, 12, 11, 10, 9, 8, 7);
375         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP))
376                 --carry;
377         nist_set_224(t_d, buf, 0, 0, 0, 0, 13, 12, 11);
378         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP))
379                 --carry;
380
381         if (carry > 0)
382                 while (carry)
383                         {
384                         if (bn_sub_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP))
385                                 --carry;
386                         }
387         else if (carry < 0)
388                 while (carry)
389                         {
390                         if (bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP))
391                                 ++carry;
392                         }
393
394         r->top = BN_NIST_224_TOP;
395         bn_correct_top(r);
396         if (BN_ucmp(r, field) >= 0)
397                 {
398                 bn_sub_words(r_d, r_d, _nist_p_224, BN_NIST_224_TOP);
399                 bn_correct_top(r);
400                 }
401         bn_check_top(r);
402         return 1;
403 #else
404         return 0;
405 #endif
406         }
407
408 static void _init_256_data(void)
409         {
410         int     i;
411         BN_ULONG *tmp1 = _256_data;
412         const BN_ULONG *tmp2 = tmp1;
413
414         memcpy(tmp1, _nist_p_256, BN_NIST_256_TOP * sizeof(BN_ULONG));
415         tmp1 += BN_NIST_256_TOP;
416
417         for (i=0; i<5; i++)
418                 {
419                 bn_add_words(tmp1, _nist_p_256, tmp2, BN_NIST_256_TOP);
420                 tmp2  = tmp1;
421                 tmp1 += BN_NIST_256_TOP;
422                 }
423         _is_set_256_data = 1;
424         }
425
426 #define nist_set_256(to, from, a1, a2, a3, a4, a5, a6, a7, a8) \
427         { \
428         if (a8 != 0) bn_cp_32(to, 0, from, (a8) - 8) else bn_32_set_0(to, 0)\
429         if (a7 != 0) bn_cp_32(to, 1, from, (a7) - 8) else bn_32_set_0(to, 1)\
430         if (a6 != 0) bn_cp_32(to, 2, from, (a6) - 8) else bn_32_set_0(to, 2)\
431         if (a5 != 0) bn_cp_32(to, 3, from, (a5) - 8) else bn_32_set_0(to, 3)\
432         if (a4 != 0) bn_cp_32(to, 4, from, (a4) - 8) else bn_32_set_0(to, 4)\
433         if (a3 != 0) bn_cp_32(to, 5, from, (a3) - 8) else bn_32_set_0(to, 5)\
434         if (a2 != 0) bn_cp_32(to, 6, from, (a2) - 8) else bn_32_set_0(to, 6)\
435         if (a1 != 0) bn_cp_32(to, 7, from, (a1) - 8) else bn_32_set_0(to, 7)\
436         }
437
438 int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
439         BN_CTX *ctx)
440         {
441 #if BN_BITS2 != 64
442         int     i, top = a->top;
443         int     carry = 0;
444         register BN_ULONG *a_d = a->d, *r_d;
445         BN_ULONG t_d[BN_NIST_256_TOP],
446                  t_d2[BN_NIST_256_TOP],
447                  buf[BN_NIST_256_TOP];
448
449         if (!_is_set_256_data)
450                 {
451                 CRYPTO_w_lock(CRYPTO_LOCK_BN);
452                 
453                 if (!_is_set_256_data)
454                         _init_256_data();
455                 
456                 CRYPTO_w_unlock(CRYPTO_LOCK_BN);
457                 }
458         
459         i = BN_ucmp(field, a);
460         if (i == 0)
461                 {
462                 BN_zero(r);
463                 return 1;
464                 }
465         else if (i > 0)
466                 return (r == a)? 1 : (BN_copy(r ,a) != NULL);
467
468         if (top == BN_NIST_256_TOP)
469                 return BN_usub(r, a, field);
470
471         if (r != a)
472                 {
473                 if (!bn_wexpand(r, BN_NIST_256_TOP))
474                         return 0;
475                 r_d = r->d;
476                 nist_cp_bn(r_d, a_d, BN_NIST_256_TOP);
477                 }
478         else
479                 r_d = a_d;
480
481         nist_cp_bn_0(buf, a_d + BN_NIST_256_TOP, top - BN_NIST_256_TOP, BN_NIST_256_TOP);
482
483         /*S1*/
484         nist_set_256(t_d, buf, 15, 14, 13, 12, 11, 0, 0, 0);
485         /*S2*/
486         nist_set_256(t_d2,buf, 0, 15, 14, 13, 12, 0, 0, 0);
487         if (bn_add_words(t_d, t_d, t_d2, BN_NIST_256_TOP))
488                 carry = 2;
489         /* left shift */
490                 {
491                 register BN_ULONG *ap,t,c;
492                 ap = t_d;
493                 c=0;
494                 for (i = BN_NIST_256_TOP; i != 0; --i)
495                         {
496                         t= *ap;
497                         *(ap++)=((t<<1)|c)&BN_MASK2;
498                         c=(t & BN_TBIT)?1:0;
499                         }
500                 if (c)
501                         ++carry;
502                 }
503
504         if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
505                 ++carry;
506         /*S3*/
507         nist_set_256(t_d, buf, 15, 14, 0, 0, 0, 10, 9, 8);
508         if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
509                 ++carry;
510         /*S4*/
511         nist_set_256(t_d, buf, 8, 13, 15, 14, 13, 11, 10, 9);
512         if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
513                 ++carry;
514         /*D1*/
515         nist_set_256(t_d, buf, 10, 8, 0, 0, 0, 13, 12, 11);
516         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
517                 --carry;
518         /*D2*/
519         nist_set_256(t_d, buf, 11, 9, 0, 0, 15, 14, 13, 12);
520         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
521                 --carry;
522         /*D3*/
523         nist_set_256(t_d, buf, 12, 0, 10, 9, 8, 15, 14, 13);
524         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
525                 --carry;
526         /*D4*/
527         nist_set_256(t_d, buf, 13, 0, 11, 10, 9, 0, 15, 14);
528         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
529                 --carry;
530         
531         if (carry)
532                 {
533                 if (carry > 0)
534                         bn_sub_words(r_d, r_d, _256_data + BN_NIST_256_TOP *
535                                 --carry, BN_NIST_256_TOP);
536                 else
537                         {
538                         carry = -carry;
539                         bn_add_words(r_d, r_d, _256_data + BN_NIST_256_TOP *
540                                 --carry, BN_NIST_256_TOP);
541                         }
542                 }
543
544         r->top = BN_NIST_256_TOP;
545         bn_correct_top(r);
546         if (BN_ucmp(r, field) >= 0)
547                 {
548                 bn_sub_words(r_d, r_d, _nist_p_256, BN_NIST_256_TOP);
549                 bn_correct_top(r);
550                 }
551         bn_check_top(r);
552         return 1;
553 #else
554         return 0;
555 #endif
556         }
557
558 static void _init_384_data(void)
559         {
560         int     i;
561         BN_ULONG *tmp1 = _384_data;
562         const BN_ULONG *tmp2 = tmp1;
563
564         memcpy(tmp1, _nist_p_384, BN_NIST_384_TOP * sizeof(BN_ULONG));
565         tmp1 += BN_NIST_384_TOP;
566
567         for (i=0; i<7; i++)
568                 {
569                 bn_add_words(tmp1, _nist_p_384, tmp2, BN_NIST_384_TOP);
570                 tmp2  = tmp1;
571                 tmp1 += BN_NIST_384_TOP;
572                 }
573         _is_set_384_data = 1;
574         }
575
576 #define nist_set_384(to,from,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \
577         { \
578         if (a12 != 0) bn_cp_32(to, 0, from,  (a12) - 12) else bn_32_set_0(to, 0)\
579         if (a11 != 0) bn_cp_32(to, 1, from,  (a11) - 12) else bn_32_set_0(to, 1)\
580         if (a10 != 0) bn_cp_32(to, 2, from,  (a10) - 12) else bn_32_set_0(to, 2)\
581         if (a9 != 0)  bn_cp_32(to, 3, from,  (a9) - 12)  else bn_32_set_0(to, 3)\
582         if (a8 != 0)  bn_cp_32(to, 4, from,  (a8) - 12)  else bn_32_set_0(to, 4)\
583         if (a7 != 0)  bn_cp_32(to, 5, from,  (a7) - 12)  else bn_32_set_0(to, 5)\
584         if (a6 != 0)  bn_cp_32(to, 6, from,  (a6) - 12)  else bn_32_set_0(to, 6)\
585         if (a5 != 0)  bn_cp_32(to, 7, from,  (a5) - 12)  else bn_32_set_0(to, 7)\
586         if (a4 != 0)  bn_cp_32(to, 8, from,  (a4) - 12)  else bn_32_set_0(to, 8)\
587         if (a3 != 0)  bn_cp_32(to, 9, from,  (a3) - 12)  else bn_32_set_0(to, 9)\
588         if (a2 != 0)  bn_cp_32(to, 10, from, (a2) - 12)  else bn_32_set_0(to, 10)\
589         if (a1 != 0)  bn_cp_32(to, 11, from, (a1) - 12)  else bn_32_set_0(to, 11)\
590         }
591
592 int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
593         BN_CTX *ctx)
594         {
595 #if BN_BITS2 != 64
596         int     i, top = a->top;
597         int     carry = 0;
598         register BN_ULONG *r_d, *a_d = a->d;
599         BN_ULONG t_d[BN_NIST_384_TOP],
600                  buf[BN_NIST_384_TOP];
601
602         if (!_is_set_384_data)
603                 {
604                 CRYPTO_w_lock(CRYPTO_LOCK_BN);
605                 
606                 if (!_is_set_384_data)
607                         _init_384_data();
608
609                 CRYPTO_w_unlock(CRYPTO_LOCK_BN);
610                 }
611
612         i = BN_ucmp(field, a);
613         if (i == 0)
614                 {
615                 BN_zero(r);
616                 return 1;
617                 }
618         else if (i > 0)
619                 return (r == a)? 1 : (BN_copy(r ,a) != NULL);
620
621         if (top == BN_NIST_384_TOP)
622                 return BN_usub(r, a, field);
623
624         if (r != a)
625                 {
626                 if (!bn_wexpand(r, BN_NIST_384_TOP))
627                         return 0;
628                 r_d = r->d;
629                 nist_cp_bn(r_d, a_d, BN_NIST_384_TOP);
630                 }
631         else
632                 r_d = a_d;
633
634         nist_cp_bn_0(buf, a_d + BN_NIST_384_TOP, top - BN_NIST_384_TOP, BN_NIST_384_TOP);
635
636         /*S1*/
637         nist_set_256(t_d, buf, 0, 0, 0, 0, 0, 23-4, 22-4, 21-4);
638                 /* left shift */
639                 {
640                 register BN_ULONG *ap,t,c;
641                 ap = t_d;
642                 c=0;
643                 for (i = BN_NIST_256_TOP; i != 0; --i)
644                         {
645                         t= *ap;
646                         *(ap++)=((t<<1)|c)&BN_MASK2;
647                         c=(t & BN_TBIT)?1:0;
648                         }
649                 }
650         if (bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
651                 t_d, BN_NIST_256_TOP))
652                 ++carry;
653         /*S2 */
654         if (bn_add_words(r_d, r_d, buf, BN_NIST_384_TOP))
655                 ++carry;
656         /*S3*/
657         nist_set_384(t_d,buf,20,19,18,17,16,15,14,13,12,23,22,21);
658         if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
659                 ++carry;
660         /*S4*/
661         nist_set_384(t_d,buf,19,18,17,16,15,14,13,12,20,0,23,0);
662         if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
663                 ++carry;
664         /*S5*/
665         nist_set_256(t_d, buf, 0, 0, 0, 0, 23-4, 22-4, 21-4, 20-4);
666         if (bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
667                 t_d, BN_NIST_256_TOP))
668                 ++carry;
669         /*S6*/
670         nist_set_384(t_d,buf,0,0,0,0,0,0,23,22,21,0,0,20);
671         if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
672                 ++carry;
673         /*D1*/
674         nist_set_384(t_d,buf,22,21,20,19,18,17,16,15,14,13,12,23);
675         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
676                 --carry;
677         /*D2*/
678         nist_set_384(t_d,buf,0,0,0,0,0,0,0,23,22,21,20,0);
679         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
680                 --carry;
681         /*D3*/
682         nist_set_384(t_d,buf,0,0,0,0,0,0,0,23,23,0,0,0);
683         if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
684                 --carry;
685         
686         if (carry)
687                 {
688                 if (carry > 0)
689                         bn_sub_words(r_d, r_d, _384_data + BN_NIST_384_TOP *
690                                 --carry, BN_NIST_384_TOP);
691                 else
692                         {
693                         carry = -carry;
694                         bn_add_words(r_d, r_d, _384_data + BN_NIST_384_TOP *
695                                 --carry, BN_NIST_384_TOP);
696                         }
697                 }
698
699         r->top = BN_NIST_384_TOP;
700         bn_correct_top(r);
701         if (BN_ucmp(r, field) >= 0)
702                 {
703                 bn_sub_words(r_d, r_d, _nist_p_384, BN_NIST_384_TOP);
704                 bn_correct_top(r);
705                 }
706         bn_check_top(r);
707         return 1;
708 #else
709         return 0;
710 #endif
711         }
712
713 int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
714         BN_CTX *ctx)
715         {
716 #if BN_BITS2 == 64
717 #define BN_NIST_521_TOP_MASK    (BN_ULONG)0x1FF
718 #elif BN_BITS2 == 32
719 #define BN_NIST_521_TOP_MASK    (BN_ULONG)0x1FF
720 #elif BN_BITS2 == 16
721 #define BN_NIST_521_TOP_MASK    (BN_ULONG)0x1FF
722 #elif BN_BITS2 == 8
723 #define BN_NIST_521_TOP_MASK    (BN_ULONG)0x1
724 #endif
725         int     top, ret = 0;
726         BN_ULONG *r_d;
727         BIGNUM  *tmp;
728
729         /* check whether a reduction is necessary */
730         top = a->top;
731         if (top < BN_NIST_521_TOP  || ( top == BN_NIST_521_TOP &&
732            (!(a->d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))))
733                 return (r == a)? 1 : (BN_copy(r ,a) != NULL);
734
735         BN_CTX_start(ctx);
736         tmp = BN_CTX_get(ctx);
737         if (!tmp)
738                 goto err;
739
740         if (!bn_wexpand(tmp, BN_NIST_521_TOP))
741                 goto err;
742         nist_cp_bn(tmp->d, a->d, BN_NIST_521_TOP);
743
744         tmp->top = BN_NIST_521_TOP;
745         tmp->d[BN_NIST_521_TOP-1]  &= BN_NIST_521_TOP_MASK;
746         bn_correct_top(tmp);
747
748         if (!BN_rshift(r, a, 521))
749                 goto err;
750
751         if (!BN_uadd(r, tmp, r))
752                 goto err;
753         top = r->top;
754         r_d = r->d;
755         if (top == BN_NIST_521_TOP  && 
756            (r_d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))
757                 {
758                 BN_NIST_ADD_ONE(r_d)
759                 r_d[BN_NIST_521_TOP-1] &= BN_NIST_521_TOP_MASK; 
760                 }
761         bn_correct_top(r);
762
763         ret = 1;
764 err:
765         BN_CTX_end(ctx);
766
767         bn_check_top(r);
768         return ret;
769         }