1160814Ssimon/* crypto/bn/bn_nist.c */
2160814Ssimon/*
3160814Ssimon * Written by Nils Larsch for the OpenSSL project
4160814Ssimon */
5160814Ssimon/* ====================================================================
6160814Ssimon * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
7160814Ssimon *
8160814Ssimon * Redistribution and use in source and binary forms, with or without
9160814Ssimon * modification, are permitted provided that the following conditions
10160814Ssimon * are met:
11160814Ssimon *
12160814Ssimon * 1. Redistributions of source code must retain the above copyright
13160814Ssimon *    notice, this list of conditions and the following disclaimer.
14160814Ssimon *
15160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
16160814Ssimon *    notice, this list of conditions and the following disclaimer in
17160814Ssimon *    the documentation and/or other materials provided with the
18160814Ssimon *    distribution.
19160814Ssimon *
20160814Ssimon * 3. All advertising materials mentioning features or use of this
21160814Ssimon *    software must display the following acknowledgment:
22160814Ssimon *    "This product includes software developed by the OpenSSL Project
23160814Ssimon *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24160814Ssimon *
25160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26160814Ssimon *    endorse or promote products derived from this software without
27160814Ssimon *    prior written permission. For written permission, please contact
28160814Ssimon *    openssl-core@openssl.org.
29160814Ssimon *
30160814Ssimon * 5. Products derived from this software may not be called "OpenSSL"
31160814Ssimon *    nor may "OpenSSL" appear in their names without prior written
32160814Ssimon *    permission of the OpenSSL Project.
33160814Ssimon *
34160814Ssimon * 6. Redistributions of any form whatsoever must retain the following
35160814Ssimon *    acknowledgment:
36160814Ssimon *    "This product includes software developed by the OpenSSL Project
37160814Ssimon *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38160814Ssimon *
39160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42160814Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
51160814Ssimon * ====================================================================
52160814Ssimon *
53160814Ssimon * This product includes cryptographic software written by Eric Young
54160814Ssimon * (eay@cryptsoft.com).  This product includes software written by Tim
55160814Ssimon * Hudson (tjh@cryptsoft.com).
56160814Ssimon *
57160814Ssimon */
58160814Ssimon
59160814Ssimon#include "bn_lcl.h"
60160814Ssimon#include "cryptlib.h"
61160814Ssimon
62194206Ssimon
63160814Ssimon#define BN_NIST_192_TOP	(192+BN_BITS2-1)/BN_BITS2
64160814Ssimon#define BN_NIST_224_TOP	(224+BN_BITS2-1)/BN_BITS2
65160814Ssimon#define BN_NIST_256_TOP	(256+BN_BITS2-1)/BN_BITS2
66160814Ssimon#define BN_NIST_384_TOP	(384+BN_BITS2-1)/BN_BITS2
67160814Ssimon#define BN_NIST_521_TOP	(521+BN_BITS2-1)/BN_BITS2
68160814Ssimon
69194206Ssimon/* pre-computed tables are "carry-less" values of modulus*(i+1) */
70160814Ssimon#if BN_BITS2 == 64
71194206Ssimonstatic const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = {
72194206Ssimon	{0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFFULL},
73194206Ssimon	{0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFDULL,0xFFFFFFFFFFFFFFFFULL},
74194206Ssimon	{0xFFFFFFFFFFFFFFFDULL,0xFFFFFFFFFFFFFFFCULL,0xFFFFFFFFFFFFFFFFULL}
75194206Ssimon	};
76194206Ssimonstatic const BN_ULONG _nist_p_192_sqr[] = {
77194206Ssimon	0x0000000000000001ULL,0x0000000000000002ULL,0x0000000000000001ULL,
78194206Ssimon	0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFDULL,0xFFFFFFFFFFFFFFFFULL
79194206Ssimon	};
80194206Ssimonstatic const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = {
81160814Ssimon	{0x0000000000000001ULL,0xFFFFFFFF00000000ULL,
82194206Ssimon	 0xFFFFFFFFFFFFFFFFULL,0x00000000FFFFFFFFULL},
83194206Ssimon	{0x0000000000000002ULL,0xFFFFFFFE00000000ULL,
84194206Ssimon	 0xFFFFFFFFFFFFFFFFULL,0x00000001FFFFFFFFULL} /* this one is "carry-full" */
85194206Ssimon	};
86194206Ssimonstatic const BN_ULONG _nist_p_224_sqr[] = {
87194206Ssimon	0x0000000000000001ULL,0xFFFFFFFE00000000ULL,
88194206Ssimon	0xFFFFFFFFFFFFFFFFULL,0x0000000200000000ULL,
89194206Ssimon	0x0000000000000000ULL,0xFFFFFFFFFFFFFFFEULL,
90194206Ssimon	0xFFFFFFFFFFFFFFFFULL
91194206Ssimon	};
92194206Ssimonstatic const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = {
93160814Ssimon	{0xFFFFFFFFFFFFFFFFULL,0x00000000FFFFFFFFULL,
94194206Ssimon	 0x0000000000000000ULL,0xFFFFFFFF00000001ULL},
95194206Ssimon	{0xFFFFFFFFFFFFFFFEULL,0x00000001FFFFFFFFULL,
96194206Ssimon	 0x0000000000000000ULL,0xFFFFFFFE00000002ULL},
97194206Ssimon	{0xFFFFFFFFFFFFFFFDULL,0x00000002FFFFFFFFULL,
98194206Ssimon	 0x0000000000000000ULL,0xFFFFFFFD00000003ULL},
99194206Ssimon	{0xFFFFFFFFFFFFFFFCULL,0x00000003FFFFFFFFULL,
100194206Ssimon	 0x0000000000000000ULL,0xFFFFFFFC00000004ULL},
101194206Ssimon	{0xFFFFFFFFFFFFFFFBULL,0x00000004FFFFFFFFULL,
102194206Ssimon	 0x0000000000000000ULL,0xFFFFFFFB00000005ULL},
103194206Ssimon	};
104194206Ssimonstatic const BN_ULONG _nist_p_256_sqr[] = {
105194206Ssimon	0x0000000000000001ULL,0xFFFFFFFE00000000ULL,
106194206Ssimon	0xFFFFFFFFFFFFFFFFULL,0x00000001FFFFFFFEULL,
107194206Ssimon	0x00000001FFFFFFFEULL,0x00000001FFFFFFFEULL,
108194206Ssimon	0xFFFFFFFE00000001ULL,0xFFFFFFFE00000002ULL
109194206Ssimon	};
110194206Ssimonstatic const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = {
111194206Ssimon	{0x00000000FFFFFFFFULL,0xFFFFFFFF00000000ULL,0xFFFFFFFFFFFFFFFEULL,
112194206Ssimon	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
113194206Ssimon	{0x00000001FFFFFFFEULL,0xFFFFFFFE00000000ULL,0xFFFFFFFFFFFFFFFDULL,
114194206Ssimon	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
115194206Ssimon	{0x00000002FFFFFFFDULL,0xFFFFFFFD00000000ULL,0xFFFFFFFFFFFFFFFCULL,
116194206Ssimon	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
117194206Ssimon	{0x00000003FFFFFFFCULL,0xFFFFFFFC00000000ULL,0xFFFFFFFFFFFFFFFBULL,
118194206Ssimon	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
119194206Ssimon	{0x00000004FFFFFFFBULL,0xFFFFFFFB00000000ULL,0xFFFFFFFFFFFFFFFAULL,
120194206Ssimon	 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL},
121194206Ssimon	};
122194206Ssimonstatic const BN_ULONG _nist_p_384_sqr[] = {
123194206Ssimon	0xFFFFFFFE00000001ULL,0x0000000200000000ULL,0xFFFFFFFE00000000ULL,
124194206Ssimon	0x0000000200000000ULL,0x0000000000000001ULL,0x0000000000000000ULL,
125194206Ssimon	0x00000001FFFFFFFEULL,0xFFFFFFFE00000000ULL,0xFFFFFFFFFFFFFFFDULL,
126194206Ssimon	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL
127194206Ssimon	};
128160814Ssimonstatic const BN_ULONG _nist_p_521[] =
129160814Ssimon	{0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
130160814Ssimon	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
131160814Ssimon	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
132160814Ssimon	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
133160814Ssimon	0x00000000000001FFULL};
134194206Ssimonstatic const BN_ULONG _nist_p_521_sqr[] = {
135194206Ssimon	0x0000000000000001ULL,0x0000000000000000ULL,0x0000000000000000ULL,
136194206Ssimon	0x0000000000000000ULL,0x0000000000000000ULL,0x0000000000000000ULL,
137194206Ssimon	0x0000000000000000ULL,0x0000000000000000ULL,0xFFFFFFFFFFFFFC00ULL,
138194206Ssimon	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
139194206Ssimon	0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
140194206Ssimon	0xFFFFFFFFFFFFFFFFULL,0x000000000003FFFFULL
141194206Ssimon	};
142160814Ssimon#elif BN_BITS2 == 32
143194206Ssimonstatic const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = {
144194206Ssimon	{0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
145194206Ssimon	{0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFD,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
146194206Ssimon	{0xFFFFFFFD,0xFFFFFFFF,0xFFFFFFFC,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}
147194206Ssimon	};
148194206Ssimonstatic const BN_ULONG _nist_p_192_sqr[] = {
149194206Ssimon	0x00000001,0x00000000,0x00000002,0x00000000,0x00000001,0x00000000,
150194206Ssimon	0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFD,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF
151194206Ssimon	};
152194206Ssimonstatic const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = {
153194206Ssimon	{0x00000001,0x00000000,0x00000000,0xFFFFFFFF,
154194206Ssimon	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
155194206Ssimon	{0x00000002,0x00000000,0x00000000,0xFFFFFFFE,
156194206Ssimon	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}
157194206Ssimon	};
158194206Ssimonstatic const BN_ULONG _nist_p_224_sqr[] = {
159194206Ssimon	0x00000001,0x00000000,0x00000000,0xFFFFFFFE,
160194206Ssimon	0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000002,
161194206Ssimon	0x00000000,0x00000000,0xFFFFFFFE,0xFFFFFFFF,
162194206Ssimon	0xFFFFFFFF,0xFFFFFFFF
163194206Ssimon	};
164194206Ssimonstatic const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = {
165194206Ssimon	{0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0x00000000,
166194206Ssimon	 0x00000000,0x00000000,0x00000001,0xFFFFFFFF},
167194206Ssimon	{0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0x00000001,
168194206Ssimon	 0x00000000,0x00000000,0x00000002,0xFFFFFFFE},
169194206Ssimon	{0xFFFFFFFD,0xFFFFFFFF,0xFFFFFFFF,0x00000002,
170194206Ssimon	 0x00000000,0x00000000,0x00000003,0xFFFFFFFD},
171194206Ssimon	{0xFFFFFFFC,0xFFFFFFFF,0xFFFFFFFF,0x00000003,
172194206Ssimon	 0x00000000,0x00000000,0x00000004,0xFFFFFFFC},
173194206Ssimon	{0xFFFFFFFB,0xFFFFFFFF,0xFFFFFFFF,0x00000004,
174194206Ssimon	 0x00000000,0x00000000,0x00000005,0xFFFFFFFB},
175194206Ssimon	};
176194206Ssimonstatic const BN_ULONG _nist_p_256_sqr[] = {
177194206Ssimon	0x00000001,0x00000000,0x00000000,0xFFFFFFFE,
178194206Ssimon	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,0x00000001,
179194206Ssimon	0xFFFFFFFE,0x00000001,0xFFFFFFFE,0x00000001,
180194206Ssimon	0x00000001,0xFFFFFFFE,0x00000002,0xFFFFFFFE
181194206Ssimon	};
182194206Ssimonstatic const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = {
183194206Ssimon	{0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF,
184194206Ssimon	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
185194206Ssimon	{0xFFFFFFFE,0x00000001,0x00000000,0xFFFFFFFE,0xFFFFFFFD,0xFFFFFFFF,
186194206Ssimon	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
187194206Ssimon	{0xFFFFFFFD,0x00000002,0x00000000,0xFFFFFFFD,0xFFFFFFFC,0xFFFFFFFF,
188194206Ssimon	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
189194206Ssimon	{0xFFFFFFFC,0x00000003,0x00000000,0xFFFFFFFC,0xFFFFFFFB,0xFFFFFFFF,
190194206Ssimon	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
191194206Ssimon	{0xFFFFFFFB,0x00000004,0x00000000,0xFFFFFFFB,0xFFFFFFFA,0xFFFFFFFF,
192194206Ssimon	 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
193194206Ssimon	};
194194206Ssimonstatic const BN_ULONG _nist_p_384_sqr[] = {
195194206Ssimon	0x00000001,0xFFFFFFFE,0x00000000,0x00000002,0x00000000,0xFFFFFFFE,
196194206Ssimon	0x00000000,0x00000002,0x00000001,0x00000000,0x00000000,0x00000000,
197194206Ssimon	0xFFFFFFFE,0x00000001,0x00000000,0xFFFFFFFE,0xFFFFFFFD,0xFFFFFFFF,
198194206Ssimon	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF
199194206Ssimon	};
200160814Ssimonstatic const BN_ULONG _nist_p_521[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
201160814Ssimon	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
202160814Ssimon	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
203160814Ssimon	0xFFFFFFFF,0x000001FF};
204194206Ssimonstatic const BN_ULONG _nist_p_521_sqr[] = {
205194206Ssimon	0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
206194206Ssimon	0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
207194206Ssimon	0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFC00,0xFFFFFFFF,
208194206Ssimon	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
209194206Ssimon	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
210194206Ssimon	0xFFFFFFFF,0xFFFFFFFF,0x0003FFFF
211194206Ssimon	};
212194206Ssimon#else
213194206Ssimon#error "unsupported BN_BITS2"
214160814Ssimon#endif
215160814Ssimon
216194206Ssimon
217194206Ssimonstatic const BIGNUM _bignum_nist_p_192 =
218194206Ssimon	{
219194206Ssimon	(BN_ULONG *)_nist_p_192[0],
220194206Ssimon	BN_NIST_192_TOP,
221194206Ssimon	BN_NIST_192_TOP,
222194206Ssimon	0,
223194206Ssimon	BN_FLG_STATIC_DATA
224194206Ssimon	};
225194206Ssimon
226194206Ssimonstatic const BIGNUM _bignum_nist_p_224 =
227194206Ssimon	{
228194206Ssimon	(BN_ULONG *)_nist_p_224[0],
229194206Ssimon	BN_NIST_224_TOP,
230194206Ssimon	BN_NIST_224_TOP,
231194206Ssimon	0,
232194206Ssimon	BN_FLG_STATIC_DATA
233194206Ssimon	};
234194206Ssimon
235194206Ssimonstatic const BIGNUM _bignum_nist_p_256 =
236194206Ssimon	{
237194206Ssimon	(BN_ULONG *)_nist_p_256[0],
238194206Ssimon	BN_NIST_256_TOP,
239194206Ssimon	BN_NIST_256_TOP,
240194206Ssimon	0,
241194206Ssimon	BN_FLG_STATIC_DATA
242194206Ssimon	};
243194206Ssimon
244194206Ssimonstatic const BIGNUM _bignum_nist_p_384 =
245194206Ssimon	{
246194206Ssimon	(BN_ULONG *)_nist_p_384[0],
247194206Ssimon	BN_NIST_384_TOP,
248194206Ssimon	BN_NIST_384_TOP,
249194206Ssimon	0,
250194206Ssimon	BN_FLG_STATIC_DATA
251194206Ssimon	};
252194206Ssimon
253194206Ssimonstatic const BIGNUM _bignum_nist_p_521 =
254194206Ssimon	{
255194206Ssimon	(BN_ULONG *)_nist_p_521,
256194206Ssimon	BN_NIST_521_TOP,
257194206Ssimon	BN_NIST_521_TOP,
258194206Ssimon	0,
259194206Ssimon	BN_FLG_STATIC_DATA
260194206Ssimon	};
261194206Ssimon
262194206Ssimon
263160814Ssimonconst BIGNUM *BN_get0_nist_prime_192(void)
264160814Ssimon	{
265194206Ssimon	return &_bignum_nist_p_192;
266160814Ssimon	}
267160814Ssimon
268160814Ssimonconst BIGNUM *BN_get0_nist_prime_224(void)
269160814Ssimon	{
270194206Ssimon	return &_bignum_nist_p_224;
271160814Ssimon	}
272160814Ssimon
273160814Ssimonconst BIGNUM *BN_get0_nist_prime_256(void)
274160814Ssimon	{
275194206Ssimon	return &_bignum_nist_p_256;
276160814Ssimon	}
277160814Ssimon
278160814Ssimonconst BIGNUM *BN_get0_nist_prime_384(void)
279160814Ssimon	{
280194206Ssimon	return &_bignum_nist_p_384;
281160814Ssimon	}
282160814Ssimon
283160814Ssimonconst BIGNUM *BN_get0_nist_prime_521(void)
284160814Ssimon	{
285194206Ssimon	return &_bignum_nist_p_521;
286160814Ssimon	}
287160814Ssimon
288160814Ssimon
289279264Sdelphijstatic void nist_cp_bn_0(BN_ULONG *dst, const BN_ULONG *src, int top, int max)
290194206Ssimon	{
291160814Ssimon	int i;
292160814Ssimon
293194206Ssimon#ifdef BN_DEBUG
294194206Ssimon	OPENSSL_assert(top <= max);
295194206Ssimon#endif
296279264Sdelphij	for (i = 0; i < top; i++)
297279264Sdelphij		dst[i] = src[i];
298279264Sdelphij	for (; i < max; i++)
299279264Sdelphij		dst[i] = 0;
300194206Ssimon	}
301194206Ssimon
302279264Sdelphijstatic void nist_cp_bn(BN_ULONG *dst, const BN_ULONG *src, int top)
303194206Ssimon	{
304160814Ssimon	int i;
305279264Sdelphij
306279264Sdelphij	for (i = 0; i < top; i++)
307279264Sdelphij		dst[i] = src[i];
308194206Ssimon	}
309160814Ssimon
310160814Ssimon#if BN_BITS2 == 64
311194206Ssimon#define bn_cp_64(to, n, from, m)	(to)[n] = (m>=0)?((from)[m]):0;
312160814Ssimon#define bn_64_set_0(to, n)		(to)[n] = (BN_ULONG)0;
313194206Ssimon/*
314194206Ssimon * two following macros are implemented under assumption that they
315194206Ssimon * are called in a sequence with *ascending* n, i.e. as they are...
316194206Ssimon */
317194206Ssimon#define bn_cp_32_naked(to, n, from, m)	(((n)&1)?(to[(n)/2]|=((m)&1)?(from[(m)/2]&BN_MASK2h):(from[(m)/2]<<32))\
318194206Ssimon						:(to[(n)/2] =((m)&1)?(from[(m)/2]>>32):(from[(m)/2]&BN_MASK2l)))
319194206Ssimon#define bn_32_set_0(to, n)		(((n)&1)?(to[(n)/2]&=BN_MASK2l):(to[(n)/2]=0));
320194206Ssimon#define bn_cp_32(to,n,from,m)		((m)>=0)?bn_cp_32_naked(to,n,from,m):bn_32_set_0(to,n)
321238405Sjkim# if defined(L_ENDIAN)
322238405Sjkim#  if defined(__arch64__)
323238405Sjkim#   define NIST_INT64 long
324238405Sjkim#  else
325238405Sjkim#   define NIST_INT64 long long
326238405Sjkim#  endif
327238405Sjkim# endif
328160814Ssimon#else
329160814Ssimon#define bn_cp_64(to, n, from, m) \
330160814Ssimon	{ \
331160814Ssimon	bn_cp_32(to, (n)*2, from, (m)*2); \
332160814Ssimon	bn_cp_32(to, (n)*2+1, from, (m)*2+1); \
333160814Ssimon	}
334160814Ssimon#define bn_64_set_0(to, n) \
335160814Ssimon	{ \
336160814Ssimon	bn_32_set_0(to, (n)*2); \
337160814Ssimon	bn_32_set_0(to, (n)*2+1); \
338160814Ssimon	}
339194206Ssimon#define bn_cp_32(to, n, from, m)	(to)[n] = (m>=0)?((from)[m]):0;
340160814Ssimon#define bn_32_set_0(to, n)		(to)[n] = (BN_ULONG)0;
341238405Sjkim# if defined(_WIN32) && !defined(__GNUC__)
342238405Sjkim#  define NIST_INT64 __int64
343238405Sjkim# elif defined(BN_LLONG)
344238405Sjkim#  define NIST_INT64 long long
345238405Sjkim# endif
346160814Ssimon#endif /* BN_BITS2 != 64 */
347160814Ssimon
348160814Ssimon#define nist_set_192(to, from, a1, a2, a3) \
349160814Ssimon	{ \
350194206Ssimon	bn_cp_64(to, 0, from, (a3) - 3) \
351160814Ssimon	bn_cp_64(to, 1, from, (a2) - 3) \
352194206Ssimon	bn_cp_64(to, 2, from, (a1) - 3) \
353160814Ssimon	}
354160814Ssimon
355160814Ssimonint BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
356160814Ssimon	BN_CTX *ctx)
357160814Ssimon	{
358160814Ssimon	int      top = a->top, i;
359194206Ssimon	int      carry;
360160814Ssimon	register BN_ULONG *r_d, *a_d = a->d;
361238405Sjkim	union	{
362238405Sjkim		BN_ULONG	bn[BN_NIST_192_TOP];
363238405Sjkim		unsigned int	ui[BN_NIST_192_TOP*sizeof(BN_ULONG)/sizeof(unsigned int)];
364238405Sjkim		} buf;
365238405Sjkim	BN_ULONG c_d[BN_NIST_192_TOP],
366194206Ssimon		*res;
367238405Sjkim	PTR_SIZE_INT mask;
368194206Ssimon	static const BIGNUM _bignum_nist_p_192_sqr = {
369194206Ssimon		(BN_ULONG *)_nist_p_192_sqr,
370194206Ssimon		sizeof(_nist_p_192_sqr)/sizeof(_nist_p_192_sqr[0]),
371194206Ssimon		sizeof(_nist_p_192_sqr)/sizeof(_nist_p_192_sqr[0]),
372194206Ssimon		0,BN_FLG_STATIC_DATA };
373160814Ssimon
374194206Ssimon	field = &_bignum_nist_p_192; /* just to make sure */
375194206Ssimon
376194206Ssimon 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_192_sqr)>=0)
377194206Ssimon		return BN_nnmod(r, a, field, ctx);
378194206Ssimon
379160814Ssimon	i = BN_ucmp(field, a);
380160814Ssimon	if (i == 0)
381160814Ssimon		{
382160814Ssimon		BN_zero(r);
383160814Ssimon		return 1;
384160814Ssimon		}
385160814Ssimon	else if (i > 0)
386160814Ssimon		return (r == a) ? 1 : (BN_copy(r ,a) != NULL);
387160814Ssimon
388160814Ssimon	if (r != a)
389160814Ssimon		{
390160814Ssimon		if (!bn_wexpand(r, BN_NIST_192_TOP))
391160814Ssimon			return 0;
392160814Ssimon		r_d = r->d;
393160814Ssimon		nist_cp_bn(r_d, a_d, BN_NIST_192_TOP);
394160814Ssimon		}
395160814Ssimon	else
396160814Ssimon		r_d = a_d;
397160814Ssimon
398238405Sjkim	nist_cp_bn_0(buf.bn, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP, BN_NIST_192_TOP);
399160814Ssimon
400238405Sjkim#if defined(NIST_INT64)
401238405Sjkim	{
402238405Sjkim	NIST_INT64		acc;	/* accumulator */
403238405Sjkim	unsigned int		*rp=(unsigned int *)r_d;
404238405Sjkim	const unsigned int	*bp=(const unsigned int *)buf.ui;
405238405Sjkim
406238405Sjkim	acc  = rp[0];	acc += bp[3*2-6];
407238405Sjkim			acc += bp[5*2-6]; rp[0] = (unsigned int)acc; acc >>= 32;
408238405Sjkim
409238405Sjkim	acc += rp[1];	acc += bp[3*2-5];
410238405Sjkim			acc += bp[5*2-5]; rp[1] = (unsigned int)acc; acc >>= 32;
411238405Sjkim
412238405Sjkim	acc += rp[2];	acc += bp[3*2-6];
413238405Sjkim			acc += bp[4*2-6];
414238405Sjkim			acc += bp[5*2-6]; rp[2] = (unsigned int)acc; acc >>= 32;
415238405Sjkim
416238405Sjkim	acc += rp[3];	acc += bp[3*2-5];
417238405Sjkim			acc += bp[4*2-5];
418238405Sjkim			acc += bp[5*2-5]; rp[3] = (unsigned int)acc; acc >>= 32;
419238405Sjkim
420238405Sjkim	acc += rp[4];	acc += bp[4*2-6];
421238405Sjkim			acc += bp[5*2-6]; rp[4] = (unsigned int)acc; acc >>= 32;
422238405Sjkim
423238405Sjkim	acc += rp[5];	acc += bp[4*2-5];
424238405Sjkim			acc += bp[5*2-5]; rp[5] = (unsigned int)acc;
425238405Sjkim
426238405Sjkim	carry = (int)(acc>>32);
427238405Sjkim	}
428238405Sjkim#else
429238405Sjkim	{
430238405Sjkim	BN_ULONG t_d[BN_NIST_192_TOP];
431238405Sjkim
432238405Sjkim	nist_set_192(t_d, buf.bn, 0, 3, 3);
433194206Ssimon	carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
434238405Sjkim	nist_set_192(t_d, buf.bn, 4, 4, 0);
435194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
436238405Sjkim	nist_set_192(t_d, buf.bn, 5, 5, 5)
437194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
438238405Sjkim	}
439238405Sjkim#endif
440194206Ssimon	if (carry > 0)
441194206Ssimon		carry = (int)bn_sub_words(r_d,r_d,_nist_p_192[carry-1],BN_NIST_192_TOP);
442194206Ssimon	else
443194206Ssimon		carry = 1;
444160814Ssimon
445194206Ssimon	/*
446194206Ssimon	 * we need 'if (carry==0 || result>=modulus) result-=modulus;'
447194206Ssimon	 * as comparison implies subtraction, we can write
448194206Ssimon	 * 'tmp=result-modulus; if (!carry || !borrow) result=tmp;'
449194206Ssimon	 * this is what happens below, but without explicit if:-) a.
450194206Ssimon	 */
451238405Sjkim	mask  = 0-(PTR_SIZE_INT)bn_sub_words(c_d,r_d,_nist_p_192[0],BN_NIST_192_TOP);
452238405Sjkim	mask &= 0-(PTR_SIZE_INT)carry;
453279264Sdelphij	res   = c_d;
454238405Sjkim	res   = (BN_ULONG *)
455279264Sdelphij	 (((PTR_SIZE_INT)res&~mask) | ((PTR_SIZE_INT)r_d&mask));
456194206Ssimon	nist_cp_bn(r_d, res, BN_NIST_192_TOP);
457160814Ssimon	r->top = BN_NIST_192_TOP;
458160814Ssimon	bn_correct_top(r);
459160814Ssimon
460160814Ssimon	return 1;
461160814Ssimon	}
462160814Ssimon
463194206Ssimontypedef BN_ULONG (*bn_addsub_f)(BN_ULONG *,const BN_ULONG *,const BN_ULONG *,int);
464194206Ssimon
465160814Ssimon#define nist_set_224(to, from, a1, a2, a3, a4, a5, a6, a7) \
466160814Ssimon	{ \
467194206Ssimon	bn_cp_32(to, 0, from, (a7) - 7) \
468194206Ssimon	bn_cp_32(to, 1, from, (a6) - 7) \
469194206Ssimon	bn_cp_32(to, 2, from, (a5) - 7) \
470194206Ssimon	bn_cp_32(to, 3, from, (a4) - 7) \
471194206Ssimon	bn_cp_32(to, 4, from, (a3) - 7) \
472194206Ssimon	bn_cp_32(to, 5, from, (a2) - 7) \
473194206Ssimon	bn_cp_32(to, 6, from, (a1) - 7) \
474160814Ssimon	}
475160814Ssimon
476160814Ssimonint BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
477160814Ssimon	BN_CTX *ctx)
478160814Ssimon	{
479160814Ssimon	int	top = a->top, i;
480194206Ssimon	int	carry;
481160814Ssimon	BN_ULONG *r_d, *a_d = a->d;
482279264Sdelphij	union	{
483279264Sdelphij		BN_ULONG	bn[BN_NIST_224_TOP];
484279264Sdelphij		unsigned int	ui[BN_NIST_224_TOP*sizeof(BN_ULONG)/sizeof(unsigned int)];
485279264Sdelphij		} buf;
486279264Sdelphij	BN_ULONG c_d[BN_NIST_224_TOP],
487194206Ssimon		*res;
488238405Sjkim	PTR_SIZE_INT mask;
489238405Sjkim	union { bn_addsub_f f; PTR_SIZE_INT p; } u;
490194206Ssimon	static const BIGNUM _bignum_nist_p_224_sqr = {
491194206Ssimon		(BN_ULONG *)_nist_p_224_sqr,
492194206Ssimon		sizeof(_nist_p_224_sqr)/sizeof(_nist_p_224_sqr[0]),
493194206Ssimon		sizeof(_nist_p_224_sqr)/sizeof(_nist_p_224_sqr[0]),
494194206Ssimon		0,BN_FLG_STATIC_DATA };
495160814Ssimon
496194206Ssimon
497194206Ssimon	field = &_bignum_nist_p_224; /* just to make sure */
498194206Ssimon
499194206Ssimon 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_224_sqr)>=0)
500194206Ssimon		return BN_nnmod(r, a, field, ctx);
501194206Ssimon
502160814Ssimon	i = BN_ucmp(field, a);
503160814Ssimon	if (i == 0)
504160814Ssimon		{
505160814Ssimon		BN_zero(r);
506160814Ssimon		return 1;
507160814Ssimon		}
508160814Ssimon	else if (i > 0)
509160814Ssimon		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
510160814Ssimon
511160814Ssimon	if (r != a)
512160814Ssimon		{
513160814Ssimon		if (!bn_wexpand(r, BN_NIST_224_TOP))
514160814Ssimon			return 0;
515160814Ssimon		r_d = r->d;
516160814Ssimon		nist_cp_bn(r_d, a_d, BN_NIST_224_TOP);
517160814Ssimon		}
518160814Ssimon	else
519160814Ssimon		r_d = a_d;
520160814Ssimon
521194206Ssimon#if BN_BITS2==64
522194206Ssimon	/* copy upper 256 bits of 448 bit number ... */
523238405Sjkim	nist_cp_bn_0(c_d, a_d + (BN_NIST_224_TOP-1), top - (BN_NIST_224_TOP-1), BN_NIST_224_TOP);
524194206Ssimon	/* ... and right shift by 32 to obtain upper 224 bits */
525279264Sdelphij	nist_set_224(buf.bn, c_d, 14, 13, 12, 11, 10, 9, 8);
526194206Ssimon	/* truncate lower part to 224 bits too */
527194206Ssimon	r_d[BN_NIST_224_TOP-1] &= BN_MASK2l;
528194206Ssimon#else
529279264Sdelphij	nist_cp_bn_0(buf.bn, a_d + BN_NIST_224_TOP, top - BN_NIST_224_TOP, BN_NIST_224_TOP);
530194206Ssimon#endif
531238405Sjkim
532238405Sjkim#if defined(NIST_INT64) && BN_BITS2!=64
533238405Sjkim	{
534238405Sjkim	NIST_INT64		acc;	/* accumulator */
535238405Sjkim	unsigned int		*rp=(unsigned int *)r_d;
536279264Sdelphij	const unsigned int	*bp=(const unsigned int *)buf.ui;
537238405Sjkim
538238405Sjkim	acc  = rp[0];	acc -= bp[7-7];
539238405Sjkim			acc -= bp[11-7]; rp[0] = (unsigned int)acc; acc >>= 32;
540238405Sjkim
541238405Sjkim	acc += rp[1];	acc -= bp[8-7];
542238405Sjkim			acc -= bp[12-7]; rp[1] = (unsigned int)acc; acc >>= 32;
543238405Sjkim
544238405Sjkim	acc += rp[2];	acc -= bp[9-7];
545238405Sjkim			acc -= bp[13-7]; rp[2] = (unsigned int)acc; acc >>= 32;
546238405Sjkim
547238405Sjkim	acc += rp[3];	acc += bp[7-7];
548238405Sjkim			acc += bp[11-7];
549238405Sjkim			acc -= bp[10-7]; rp[3] = (unsigned int)acc; acc>>= 32;
550238405Sjkim
551238405Sjkim	acc += rp[4];	acc += bp[8-7];
552238405Sjkim			acc += bp[12-7];
553238405Sjkim			acc -= bp[11-7]; rp[4] = (unsigned int)acc; acc >>= 32;
554238405Sjkim
555238405Sjkim	acc += rp[5];	acc += bp[9-7];
556238405Sjkim			acc += bp[13-7];
557238405Sjkim			acc -= bp[12-7]; rp[5] = (unsigned int)acc; acc >>= 32;
558238405Sjkim
559238405Sjkim	acc += rp[6];	acc += bp[10-7];
560238405Sjkim			acc -= bp[13-7]; rp[6] = (unsigned int)acc;
561238405Sjkim
562238405Sjkim	carry = (int)(acc>>32);
563238405Sjkim# if BN_BITS2==64
564238405Sjkim	rp[7] = carry;
565238405Sjkim# endif
566238405Sjkim	}
567238405Sjkim#else
568238405Sjkim	{
569238405Sjkim	BN_ULONG t_d[BN_NIST_224_TOP];
570238405Sjkim
571279264Sdelphij	nist_set_224(t_d, buf.bn, 10, 9, 8, 7, 0, 0, 0);
572194206Ssimon	carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
573279264Sdelphij	nist_set_224(t_d, buf.bn, 0, 13, 12, 11, 0, 0, 0);
574194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
575279264Sdelphij	nist_set_224(t_d, buf.bn, 13, 12, 11, 10, 9, 8, 7);
576194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP);
577279264Sdelphij	nist_set_224(t_d, buf.bn, 0, 0, 0, 0, 13, 12, 11);
578194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP);
579160814Ssimon
580194206Ssimon#if BN_BITS2==64
581194206Ssimon	carry = (int)(r_d[BN_NIST_224_TOP-1]>>32);
582194206Ssimon#endif
583238405Sjkim	}
584238405Sjkim#endif
585194206Ssimon	u.f = bn_sub_words;
586160814Ssimon	if (carry > 0)
587194206Ssimon		{
588194206Ssimon		carry = (int)bn_sub_words(r_d,r_d,_nist_p_224[carry-1],BN_NIST_224_TOP);
589194206Ssimon#if BN_BITS2==64
590194206Ssimon		carry=(int)(~(r_d[BN_NIST_224_TOP-1]>>32))&1;
591194206Ssimon#endif
592194206Ssimon		}
593160814Ssimon	else if (carry < 0)
594194206Ssimon		{
595194206Ssimon		/* it's a bit more comlicated logic in this case.
596194206Ssimon		 * if bn_add_words yields no carry, then result
597194206Ssimon		 * has to be adjusted by unconditionally *adding*
598194206Ssimon		 * the modulus. but if it does, then result has
599194206Ssimon		 * to be compared to the modulus and conditionally
600194206Ssimon		 * adjusted by *subtracting* the latter. */
601194206Ssimon		carry = (int)bn_add_words(r_d,r_d,_nist_p_224[-carry-1],BN_NIST_224_TOP);
602238405Sjkim		mask = 0-(PTR_SIZE_INT)carry;
603238405Sjkim		u.p = ((PTR_SIZE_INT)bn_sub_words&mask) |
604238405Sjkim		 ((PTR_SIZE_INT)bn_add_words&~mask);
605194206Ssimon		}
606194206Ssimon	else
607194206Ssimon		carry = 1;
608160814Ssimon
609194206Ssimon	/* otherwise it's effectively same as in BN_nist_mod_192... */
610238405Sjkim	mask  = 0-(PTR_SIZE_INT)(*u.f)(c_d,r_d,_nist_p_224[0],BN_NIST_224_TOP);
611238405Sjkim	mask &= 0-(PTR_SIZE_INT)carry;
612279264Sdelphij	res   = c_d;
613279264Sdelphij	res   = (BN_ULONG *)(((PTR_SIZE_INT)res&~mask) |
614238405Sjkim	 ((PTR_SIZE_INT)r_d&mask));
615194206Ssimon	nist_cp_bn(r_d, res, BN_NIST_224_TOP);
616160814Ssimon	r->top = BN_NIST_224_TOP;
617160814Ssimon	bn_correct_top(r);
618194206Ssimon
619160814Ssimon	return 1;
620160814Ssimon	}
621160814Ssimon
622160814Ssimon#define nist_set_256(to, from, a1, a2, a3, a4, a5, a6, a7, a8) \
623160814Ssimon	{ \
624194206Ssimon	bn_cp_32(to, 0, from, (a8) - 8) \
625194206Ssimon	bn_cp_32(to, 1, from, (a7) - 8) \
626194206Ssimon	bn_cp_32(to, 2, from, (a6) - 8) \
627194206Ssimon	bn_cp_32(to, 3, from, (a5) - 8) \
628194206Ssimon	bn_cp_32(to, 4, from, (a4) - 8) \
629194206Ssimon	bn_cp_32(to, 5, from, (a3) - 8) \
630194206Ssimon	bn_cp_32(to, 6, from, (a2) - 8) \
631194206Ssimon	bn_cp_32(to, 7, from, (a1) - 8) \
632160814Ssimon	}
633160814Ssimon
634160814Ssimonint BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
635160814Ssimon	BN_CTX *ctx)
636160814Ssimon	{
637160814Ssimon	int	i, top = a->top;
638160814Ssimon	int	carry = 0;
639160814Ssimon	register BN_ULONG *a_d = a->d, *r_d;
640238405Sjkim	union	{
641238405Sjkim		BN_ULONG bn[BN_NIST_256_TOP];
642238405Sjkim		unsigned int ui[BN_NIST_256_TOP*sizeof(BN_ULONG)/sizeof(unsigned int)];
643238405Sjkim		} buf;
644238405Sjkim	BN_ULONG c_d[BN_NIST_256_TOP],
645194206Ssimon		*res;
646238405Sjkim	PTR_SIZE_INT mask;
647238405Sjkim	union { bn_addsub_f f; PTR_SIZE_INT p; } u;
648194206Ssimon	static const BIGNUM _bignum_nist_p_256_sqr = {
649194206Ssimon		(BN_ULONG *)_nist_p_256_sqr,
650194206Ssimon		sizeof(_nist_p_256_sqr)/sizeof(_nist_p_256_sqr[0]),
651194206Ssimon		sizeof(_nist_p_256_sqr)/sizeof(_nist_p_256_sqr[0]),
652194206Ssimon		0,BN_FLG_STATIC_DATA };
653160814Ssimon
654194206Ssimon	field = &_bignum_nist_p_256; /* just to make sure */
655194206Ssimon
656194206Ssimon 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_256_sqr)>=0)
657194206Ssimon		return BN_nnmod(r, a, field, ctx);
658194206Ssimon
659160814Ssimon	i = BN_ucmp(field, a);
660160814Ssimon	if (i == 0)
661160814Ssimon		{
662160814Ssimon		BN_zero(r);
663160814Ssimon		return 1;
664160814Ssimon		}
665160814Ssimon	else if (i > 0)
666160814Ssimon		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
667160814Ssimon
668160814Ssimon	if (r != a)
669160814Ssimon		{
670160814Ssimon		if (!bn_wexpand(r, BN_NIST_256_TOP))
671160814Ssimon			return 0;
672160814Ssimon		r_d = r->d;
673160814Ssimon		nist_cp_bn(r_d, a_d, BN_NIST_256_TOP);
674160814Ssimon		}
675160814Ssimon	else
676160814Ssimon		r_d = a_d;
677160814Ssimon
678238405Sjkim	nist_cp_bn_0(buf.bn, a_d + BN_NIST_256_TOP, top - BN_NIST_256_TOP, BN_NIST_256_TOP);
679160814Ssimon
680238405Sjkim#if defined(NIST_INT64)
681238405Sjkim	{
682238405Sjkim	NIST_INT64		acc;	/* accumulator */
683238405Sjkim	unsigned int		*rp=(unsigned int *)r_d;
684238405Sjkim	const unsigned int	*bp=(const unsigned int *)buf.ui;
685238405Sjkim
686238405Sjkim	acc = rp[0];	acc += bp[8-8];
687238405Sjkim			acc += bp[9-8];
688238405Sjkim			acc -= bp[11-8];
689238405Sjkim			acc -= bp[12-8];
690238405Sjkim			acc -= bp[13-8];
691238405Sjkim			acc -= bp[14-8]; rp[0] = (unsigned int)acc; acc >>= 32;
692238405Sjkim
693238405Sjkim	acc += rp[1];	acc += bp[9-8];
694238405Sjkim			acc += bp[10-8];
695238405Sjkim			acc -= bp[12-8];
696238405Sjkim			acc -= bp[13-8];
697238405Sjkim			acc -= bp[14-8];
698238405Sjkim			acc -= bp[15-8]; rp[1] = (unsigned int)acc; acc >>= 32;
699238405Sjkim
700238405Sjkim	acc += rp[2];	acc += bp[10-8];
701238405Sjkim			acc += bp[11-8];
702238405Sjkim			acc -= bp[13-8];
703238405Sjkim			acc -= bp[14-8];
704238405Sjkim			acc -= bp[15-8]; rp[2] = (unsigned int)acc; acc >>= 32;
705238405Sjkim
706238405Sjkim	acc += rp[3];	acc += bp[11-8];
707238405Sjkim			acc += bp[11-8];
708238405Sjkim			acc += bp[12-8];
709238405Sjkim			acc += bp[12-8];
710238405Sjkim			acc += bp[13-8];
711238405Sjkim			acc -= bp[15-8];
712238405Sjkim			acc -= bp[8-8];
713238405Sjkim			acc -= bp[9-8];  rp[3] = (unsigned int)acc; acc >>= 32;
714238405Sjkim
715238405Sjkim	acc += rp[4];	acc += bp[12-8];
716238405Sjkim			acc += bp[12-8];
717238405Sjkim			acc += bp[13-8];
718238405Sjkim			acc += bp[13-8];
719238405Sjkim			acc += bp[14-8];
720238405Sjkim			acc -= bp[9-8];
721238405Sjkim			acc -= bp[10-8]; rp[4] = (unsigned int)acc; acc >>= 32;
722238405Sjkim
723238405Sjkim	acc += rp[5];	acc += bp[13-8];
724238405Sjkim			acc += bp[13-8];
725238405Sjkim			acc += bp[14-8];
726238405Sjkim			acc += bp[14-8];
727238405Sjkim			acc += bp[15-8];
728238405Sjkim			acc -= bp[10-8];
729238405Sjkim			acc -= bp[11-8]; rp[5] = (unsigned int)acc; acc >>= 32;
730238405Sjkim
731238405Sjkim	acc += rp[6];	acc += bp[14-8];
732238405Sjkim			acc += bp[14-8];
733238405Sjkim			acc += bp[15-8];
734238405Sjkim			acc += bp[15-8];
735238405Sjkim			acc += bp[14-8];
736238405Sjkim			acc += bp[13-8];
737238405Sjkim			acc -= bp[8-8];
738238405Sjkim			acc -= bp[9-8];  rp[6] = (unsigned int)acc; acc >>= 32;
739238405Sjkim
740238405Sjkim	acc += rp[7];	acc += bp[15-8];
741238405Sjkim			acc += bp[15-8];
742238405Sjkim			acc += bp[15-8];
743238405Sjkim			acc += bp[8 -8];
744238405Sjkim			acc -= bp[10-8];
745238405Sjkim			acc -= bp[11-8];
746238405Sjkim			acc -= bp[12-8];
747238405Sjkim			acc -= bp[13-8]; rp[7] = (unsigned int)acc;
748238405Sjkim
749238405Sjkim	carry = (int)(acc>>32);
750238405Sjkim	}
751238405Sjkim#else
752238405Sjkim	{
753238405Sjkim	BN_ULONG t_d[BN_NIST_256_TOP];
754238405Sjkim
755160814Ssimon	/*S1*/
756238405Sjkim	nist_set_256(t_d, buf.bn, 15, 14, 13, 12, 11, 0, 0, 0);
757160814Ssimon	/*S2*/
758238405Sjkim	nist_set_256(c_d, buf.bn, 0, 15, 14, 13, 12, 0, 0, 0);
759194206Ssimon	carry = (int)bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP);
760160814Ssimon	/* left shift */
761160814Ssimon		{
762160814Ssimon		register BN_ULONG *ap,t,c;
763160814Ssimon		ap = t_d;
764160814Ssimon		c=0;
765160814Ssimon		for (i = BN_NIST_256_TOP; i != 0; --i)
766160814Ssimon			{
767160814Ssimon			t= *ap;
768160814Ssimon			*(ap++)=((t<<1)|c)&BN_MASK2;
769160814Ssimon			c=(t & BN_TBIT)?1:0;
770160814Ssimon			}
771194206Ssimon		carry <<= 1;
772194206Ssimon		carry  |= c;
773160814Ssimon		}
774194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
775160814Ssimon	/*S3*/
776238405Sjkim	nist_set_256(t_d, buf.bn, 15, 14, 0, 0, 0, 10, 9, 8);
777194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
778160814Ssimon	/*S4*/
779238405Sjkim	nist_set_256(t_d, buf.bn, 8, 13, 15, 14, 13, 11, 10, 9);
780194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
781160814Ssimon	/*D1*/
782238405Sjkim	nist_set_256(t_d, buf.bn, 10, 8, 0, 0, 0, 13, 12, 11);
783194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
784160814Ssimon	/*D2*/
785238405Sjkim	nist_set_256(t_d, buf.bn, 11, 9, 0, 0, 15, 14, 13, 12);
786194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
787160814Ssimon	/*D3*/
788238405Sjkim	nist_set_256(t_d, buf.bn, 12, 0, 10, 9, 8, 15, 14, 13);
789194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
790160814Ssimon	/*D4*/
791238405Sjkim	nist_set_256(t_d, buf.bn, 13, 0, 11, 10, 9, 0, 15, 14);
792194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
793194206Ssimon
794238405Sjkim	}
795238405Sjkim#endif
796194206Ssimon	/* see BN_nist_mod_224 for explanation */
797194206Ssimon	u.f = bn_sub_words;
798194206Ssimon	if (carry > 0)
799194206Ssimon		carry = (int)bn_sub_words(r_d,r_d,_nist_p_256[carry-1],BN_NIST_256_TOP);
800194206Ssimon	else if (carry < 0)
801160814Ssimon		{
802194206Ssimon		carry = (int)bn_add_words(r_d,r_d,_nist_p_256[-carry-1],BN_NIST_256_TOP);
803238405Sjkim		mask = 0-(PTR_SIZE_INT)carry;
804238405Sjkim		u.p = ((PTR_SIZE_INT)bn_sub_words&mask) |
805238405Sjkim		 ((PTR_SIZE_INT)bn_add_words&~mask);
806160814Ssimon		}
807194206Ssimon	else
808194206Ssimon		carry = 1;
809160814Ssimon
810238405Sjkim	mask  = 0-(PTR_SIZE_INT)(*u.f)(c_d,r_d,_nist_p_256[0],BN_NIST_256_TOP);
811238405Sjkim	mask &= 0-(PTR_SIZE_INT)carry;
812279264Sdelphij	res   = c_d;
813279264Sdelphij	res   = (BN_ULONG *)(((PTR_SIZE_INT)res&~mask) |
814238405Sjkim	 ((PTR_SIZE_INT)r_d&mask));
815194206Ssimon	nist_cp_bn(r_d, res, BN_NIST_256_TOP);
816160814Ssimon	r->top = BN_NIST_256_TOP;
817160814Ssimon	bn_correct_top(r);
818194206Ssimon
819160814Ssimon	return 1;
820160814Ssimon	}
821160814Ssimon
822160814Ssimon#define nist_set_384(to,from,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \
823160814Ssimon	{ \
824194206Ssimon	bn_cp_32(to, 0, from,  (a12) - 12) \
825194206Ssimon	bn_cp_32(to, 1, from,  (a11) - 12) \
826194206Ssimon	bn_cp_32(to, 2, from,  (a10) - 12) \
827194206Ssimon	bn_cp_32(to, 3, from,  (a9) - 12)  \
828194206Ssimon	bn_cp_32(to, 4, from,  (a8) - 12)  \
829194206Ssimon	bn_cp_32(to, 5, from,  (a7) - 12)  \
830194206Ssimon	bn_cp_32(to, 6, from,  (a6) - 12)  \
831194206Ssimon	bn_cp_32(to, 7, from,  (a5) - 12)  \
832194206Ssimon	bn_cp_32(to, 8, from,  (a4) - 12)  \
833194206Ssimon	bn_cp_32(to, 9, from,  (a3) - 12)  \
834194206Ssimon	bn_cp_32(to, 10, from, (a2) - 12)  \
835194206Ssimon	bn_cp_32(to, 11, from, (a1) - 12)  \
836160814Ssimon	}
837160814Ssimon
838160814Ssimonint BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
839160814Ssimon	BN_CTX *ctx)
840160814Ssimon	{
841160814Ssimon	int	i, top = a->top;
842160814Ssimon	int	carry = 0;
843160814Ssimon	register BN_ULONG *r_d, *a_d = a->d;
844238405Sjkim	union	{
845238405Sjkim		BN_ULONG bn[BN_NIST_384_TOP];
846238405Sjkim		unsigned int ui[BN_NIST_384_TOP*sizeof(BN_ULONG)/sizeof(unsigned int)];
847238405Sjkim		} buf;
848238405Sjkim	BN_ULONG c_d[BN_NIST_384_TOP],
849194206Ssimon		*res;
850238405Sjkim	PTR_SIZE_INT mask;
851238405Sjkim	union { bn_addsub_f f; PTR_SIZE_INT p; } u;
852194206Ssimon	static const BIGNUM _bignum_nist_p_384_sqr = {
853194206Ssimon		(BN_ULONG *)_nist_p_384_sqr,
854194206Ssimon		sizeof(_nist_p_384_sqr)/sizeof(_nist_p_384_sqr[0]),
855194206Ssimon		sizeof(_nist_p_384_sqr)/sizeof(_nist_p_384_sqr[0]),
856194206Ssimon		0,BN_FLG_STATIC_DATA };
857160814Ssimon
858160814Ssimon
859194206Ssimon	field = &_bignum_nist_p_384; /* just to make sure */
860160814Ssimon
861194206Ssimon 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_384_sqr)>=0)
862194206Ssimon		return BN_nnmod(r, a, field, ctx);
863194206Ssimon
864160814Ssimon	i = BN_ucmp(field, a);
865160814Ssimon	if (i == 0)
866160814Ssimon		{
867160814Ssimon		BN_zero(r);
868160814Ssimon		return 1;
869160814Ssimon		}
870160814Ssimon	else if (i > 0)
871160814Ssimon		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
872160814Ssimon
873160814Ssimon	if (r != a)
874160814Ssimon		{
875160814Ssimon		if (!bn_wexpand(r, BN_NIST_384_TOP))
876160814Ssimon			return 0;
877160814Ssimon		r_d = r->d;
878160814Ssimon		nist_cp_bn(r_d, a_d, BN_NIST_384_TOP);
879160814Ssimon		}
880160814Ssimon	else
881160814Ssimon		r_d = a_d;
882160814Ssimon
883238405Sjkim	nist_cp_bn_0(buf.bn, a_d + BN_NIST_384_TOP, top - BN_NIST_384_TOP, BN_NIST_384_TOP);
884160814Ssimon
885238405Sjkim#if defined(NIST_INT64)
886238405Sjkim	{
887238405Sjkim	NIST_INT64		acc;	/* accumulator */
888238405Sjkim	unsigned int		*rp=(unsigned int *)r_d;
889238405Sjkim	const unsigned int	*bp=(const unsigned int *)buf.ui;
890238405Sjkim
891238405Sjkim	acc = rp[0];	acc += bp[12-12];
892238405Sjkim			acc += bp[21-12];
893238405Sjkim			acc += bp[20-12];
894238405Sjkim			acc -= bp[23-12]; rp[0] = (unsigned int)acc; acc >>= 32;
895238405Sjkim
896238405Sjkim	acc += rp[1];	acc += bp[13-12];
897238405Sjkim			acc += bp[22-12];
898238405Sjkim			acc += bp[23-12];
899238405Sjkim			acc -= bp[12-12];
900238405Sjkim			acc -= bp[20-12]; rp[1] = (unsigned int)acc; acc >>= 32;
901238405Sjkim
902238405Sjkim	acc += rp[2];	acc += bp[14-12];
903238405Sjkim			acc += bp[23-12];
904238405Sjkim			acc -= bp[13-12];
905238405Sjkim			acc -= bp[21-12]; rp[2] = (unsigned int)acc; acc >>= 32;
906238405Sjkim
907238405Sjkim	acc += rp[3];	acc += bp[15-12];
908238405Sjkim			acc += bp[12-12];
909238405Sjkim			acc += bp[20-12];
910238405Sjkim			acc += bp[21-12];
911238405Sjkim			acc -= bp[14-12];
912238405Sjkim			acc -= bp[22-12];
913238405Sjkim			acc -= bp[23-12]; rp[3] = (unsigned int)acc; acc >>= 32;
914238405Sjkim
915238405Sjkim	acc += rp[4];	acc += bp[21-12];
916238405Sjkim			acc += bp[21-12];
917238405Sjkim			acc += bp[16-12];
918238405Sjkim			acc += bp[13-12];
919238405Sjkim			acc += bp[12-12];
920238405Sjkim			acc += bp[20-12];
921238405Sjkim			acc += bp[22-12];
922238405Sjkim			acc -= bp[15-12];
923238405Sjkim			acc -= bp[23-12];
924238405Sjkim			acc -= bp[23-12]; rp[4] = (unsigned int)acc; acc >>= 32;
925238405Sjkim
926238405Sjkim	acc += rp[5];	acc += bp[22-12];
927238405Sjkim			acc += bp[22-12];
928238405Sjkim			acc += bp[17-12];
929238405Sjkim			acc += bp[14-12];
930238405Sjkim			acc += bp[13-12];
931238405Sjkim			acc += bp[21-12];
932238405Sjkim			acc += bp[23-12];
933238405Sjkim			acc -= bp[16-12]; rp[5] = (unsigned int)acc; acc >>= 32;
934238405Sjkim
935238405Sjkim	acc += rp[6];	acc += bp[23-12];
936238405Sjkim			acc += bp[23-12];
937238405Sjkim			acc += bp[18-12];
938238405Sjkim			acc += bp[15-12];
939238405Sjkim			acc += bp[14-12];
940238405Sjkim			acc += bp[22-12];
941238405Sjkim			acc -= bp[17-12]; rp[6] = (unsigned int)acc; acc >>= 32;
942238405Sjkim
943238405Sjkim	acc += rp[7];	acc += bp[19-12];
944238405Sjkim			acc += bp[16-12];
945238405Sjkim			acc += bp[15-12];
946238405Sjkim			acc += bp[23-12];
947238405Sjkim			acc -= bp[18-12]; rp[7] = (unsigned int)acc; acc >>= 32;
948238405Sjkim
949238405Sjkim	acc += rp[8];	acc += bp[20-12];
950238405Sjkim			acc += bp[17-12];
951238405Sjkim			acc += bp[16-12];
952238405Sjkim			acc -= bp[19-12]; rp[8] = (unsigned int)acc; acc >>= 32;
953238405Sjkim
954238405Sjkim	acc += rp[9];	acc += bp[21-12];
955238405Sjkim			acc += bp[18-12];
956238405Sjkim			acc += bp[17-12];
957238405Sjkim			acc -= bp[20-12]; rp[9] = (unsigned int)acc; acc >>= 32;
958238405Sjkim
959238405Sjkim	acc += rp[10];	acc += bp[22-12];
960238405Sjkim			acc += bp[19-12];
961238405Sjkim			acc += bp[18-12];
962238405Sjkim			acc -= bp[21-12]; rp[10] = (unsigned int)acc; acc >>= 32;
963238405Sjkim
964238405Sjkim	acc += rp[11];	acc += bp[23-12];
965238405Sjkim			acc += bp[20-12];
966238405Sjkim			acc += bp[19-12];
967238405Sjkim			acc -= bp[22-12]; rp[11] = (unsigned int)acc;
968238405Sjkim
969238405Sjkim	carry = (int)(acc>>32);
970238405Sjkim	}
971238405Sjkim#else
972238405Sjkim	{
973238405Sjkim	BN_ULONG t_d[BN_NIST_384_TOP];
974238405Sjkim
975160814Ssimon	/*S1*/
976238405Sjkim	nist_set_256(t_d, buf.bn, 0, 0, 0, 0, 0, 23-4, 22-4, 21-4);
977160814Ssimon		/* left shift */
978160814Ssimon		{
979160814Ssimon		register BN_ULONG *ap,t,c;
980160814Ssimon		ap = t_d;
981160814Ssimon		c=0;
982194206Ssimon		for (i = 3; i != 0; --i)
983160814Ssimon			{
984160814Ssimon			t= *ap;
985160814Ssimon			*(ap++)=((t<<1)|c)&BN_MASK2;
986160814Ssimon			c=(t & BN_TBIT)?1:0;
987160814Ssimon			}
988194206Ssimon		*ap=c;
989160814Ssimon		}
990194206Ssimon	carry = (int)bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2),
991194206Ssimon		t_d, BN_NIST_256_TOP);
992160814Ssimon	/*S2 */
993238405Sjkim	carry += (int)bn_add_words(r_d, r_d, buf.bn, BN_NIST_384_TOP);
994160814Ssimon	/*S3*/
995238405Sjkim	nist_set_384(t_d,buf.bn,20,19,18,17,16,15,14,13,12,23,22,21);
996194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
997160814Ssimon	/*S4*/
998238405Sjkim	nist_set_384(t_d,buf.bn,19,18,17,16,15,14,13,12,20,0,23,0);
999194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
1000160814Ssimon	/*S5*/
1001238405Sjkim	nist_set_384(t_d, buf.bn,0,0,0,0,23,22,21,20,0,0,0,0);
1002194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
1003160814Ssimon	/*S6*/
1004238405Sjkim	nist_set_384(t_d,buf.bn,0,0,0,0,0,0,23,22,21,0,0,20);
1005194206Ssimon	carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
1006160814Ssimon	/*D1*/
1007238405Sjkim	nist_set_384(t_d,buf.bn,22,21,20,19,18,17,16,15,14,13,12,23);
1008194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
1009160814Ssimon	/*D2*/
1010238405Sjkim	nist_set_384(t_d,buf.bn,0,0,0,0,0,0,0,23,22,21,20,0);
1011194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
1012160814Ssimon	/*D3*/
1013238405Sjkim	nist_set_384(t_d,buf.bn,0,0,0,0,0,0,0,23,23,0,0,0);
1014194206Ssimon	carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
1015194206Ssimon
1016238405Sjkim	}
1017238405Sjkim#endif
1018194206Ssimon	/* see BN_nist_mod_224 for explanation */
1019194206Ssimon	u.f = bn_sub_words;
1020194206Ssimon	if (carry > 0)
1021194206Ssimon		carry = (int)bn_sub_words(r_d,r_d,_nist_p_384[carry-1],BN_NIST_384_TOP);
1022194206Ssimon	else if (carry < 0)
1023160814Ssimon		{
1024194206Ssimon		carry = (int)bn_add_words(r_d,r_d,_nist_p_384[-carry-1],BN_NIST_384_TOP);
1025238405Sjkim		mask = 0-(PTR_SIZE_INT)carry;
1026238405Sjkim		u.p = ((PTR_SIZE_INT)bn_sub_words&mask) |
1027238405Sjkim		 ((PTR_SIZE_INT)bn_add_words&~mask);
1028160814Ssimon		}
1029194206Ssimon	else
1030194206Ssimon		carry = 1;
1031160814Ssimon
1032238405Sjkim	mask  = 0-(PTR_SIZE_INT)(*u.f)(c_d,r_d,_nist_p_384[0],BN_NIST_384_TOP);
1033238405Sjkim	mask &= 0-(PTR_SIZE_INT)carry;
1034279264Sdelphij	res   = c_d;
1035279264Sdelphij	res   = (BN_ULONG *)(((PTR_SIZE_INT)res&~mask) |
1036238405Sjkim	 ((PTR_SIZE_INT)r_d&mask));
1037194206Ssimon	nist_cp_bn(r_d, res, BN_NIST_384_TOP);
1038160814Ssimon	r->top = BN_NIST_384_TOP;
1039160814Ssimon	bn_correct_top(r);
1040194206Ssimon
1041160814Ssimon	return 1;
1042160814Ssimon	}
1043160814Ssimon
1044194206Ssimon#define BN_NIST_521_RSHIFT	(521%BN_BITS2)
1045194206Ssimon#define BN_NIST_521_LSHIFT	(BN_BITS2-BN_NIST_521_RSHIFT)
1046194206Ssimon#define BN_NIST_521_TOP_MASK	((BN_ULONG)BN_MASK2>>BN_NIST_521_LSHIFT)
1047194206Ssimon
1048160814Ssimonint BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
1049160814Ssimon	BN_CTX *ctx)
1050160814Ssimon	{
1051194206Ssimon	int	top = a->top, i;
1052194206Ssimon	BN_ULONG *r_d, *a_d = a->d,
1053194206Ssimon		 t_d[BN_NIST_521_TOP],
1054194206Ssimon		 val,tmp,*res;
1055238405Sjkim	PTR_SIZE_INT mask;
1056194206Ssimon	static const BIGNUM _bignum_nist_p_521_sqr = {
1057194206Ssimon		(BN_ULONG *)_nist_p_521_sqr,
1058194206Ssimon		sizeof(_nist_p_521_sqr)/sizeof(_nist_p_521_sqr[0]),
1059194206Ssimon		sizeof(_nist_p_521_sqr)/sizeof(_nist_p_521_sqr[0]),
1060194206Ssimon		0,BN_FLG_STATIC_DATA };
1061160814Ssimon
1062194206Ssimon	field = &_bignum_nist_p_521; /* just to make sure */
1063160814Ssimon
1064194206Ssimon 	if (BN_is_negative(a) || BN_ucmp(a,&_bignum_nist_p_521_sqr)>=0)
1065194206Ssimon		return BN_nnmod(r, a, field, ctx);
1066160814Ssimon
1067194206Ssimon	i = BN_ucmp(field, a);
1068194206Ssimon	if (i == 0)
1069194206Ssimon		{
1070194206Ssimon		BN_zero(r);
1071194206Ssimon		return 1;
1072194206Ssimon		}
1073194206Ssimon	else if (i > 0)
1074194206Ssimon		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
1075160814Ssimon
1076194206Ssimon	if (r != a)
1077194206Ssimon		{
1078194206Ssimon		if (!bn_wexpand(r,BN_NIST_521_TOP))
1079194206Ssimon			return 0;
1080194206Ssimon		r_d = r->d;
1081194206Ssimon		nist_cp_bn(r_d,a_d, BN_NIST_521_TOP);
1082194206Ssimon		}
1083194206Ssimon	else
1084194206Ssimon		r_d = a_d;
1085160814Ssimon
1086194206Ssimon	/* upper 521 bits, copy ... */
1087194206Ssimon	nist_cp_bn_0(t_d,a_d + (BN_NIST_521_TOP-1), top - (BN_NIST_521_TOP-1),BN_NIST_521_TOP);
1088194206Ssimon	/* ... and right shift */
1089194206Ssimon	for (val=t_d[0],i=0; i<BN_NIST_521_TOP-1; i++)
1090160814Ssimon		{
1091279264Sdelphij		t_d[i] = ( val>>BN_NIST_521_RSHIFT |
1092279264Sdelphij			  (tmp=t_d[i+1])<<BN_NIST_521_LSHIFT ) & BN_MASK2;
1093279264Sdelphij		val=tmp;
1094160814Ssimon		}
1095194206Ssimon	t_d[i] = val>>BN_NIST_521_RSHIFT;
1096194206Ssimon	/* lower 521 bits */
1097194206Ssimon	r_d[i] &= BN_NIST_521_TOP_MASK;
1098194206Ssimon
1099194206Ssimon	bn_add_words(r_d,r_d,t_d,BN_NIST_521_TOP);
1100238405Sjkim	mask = 0-(PTR_SIZE_INT)bn_sub_words(t_d,r_d,_nist_p_521,BN_NIST_521_TOP);
1101279264Sdelphij	res  = t_d;
1102279264Sdelphij	res  = (BN_ULONG *)(((PTR_SIZE_INT)res&~mask) |
1103238405Sjkim	 ((PTR_SIZE_INT)r_d&mask));
1104194206Ssimon	nist_cp_bn(r_d,res,BN_NIST_521_TOP);
1105194206Ssimon	r->top = BN_NIST_521_TOP;
1106160814Ssimon	bn_correct_top(r);
1107160814Ssimon
1108194206Ssimon	return 1;
1109160814Ssimon	}
1110