1/* crypto/bn/bn_exp.c */
2/* Copyright (C) 1995-1998 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 * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
60 *
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
63 * are met:
64 *
65 * 1. Redistributions of source code must retain the above copyright
66 *    notice, this list of conditions and the following disclaimer.
67 *
68 * 2. Redistributions in binary form must reproduce the above copyright
69 *    notice, this list of conditions and the following disclaimer in
70 *    the documentation and/or other materials provided with the
71 *    distribution.
72 *
73 * 3. All advertising materials mentioning features or use of this
74 *    software must display the following acknowledgment:
75 *    "This product includes software developed by the OpenSSL Project
76 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77 *
78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79 *    endorse or promote products derived from this software without
80 *    prior written permission. For written permission, please contact
81 *    openssl-core@openssl.org.
82 *
83 * 5. Products derived from this software may not be called "OpenSSL"
84 *    nor may "OpenSSL" appear in their names without prior written
85 *    permission of the OpenSSL Project.
86 *
87 * 6. Redistributions of any form whatsoever must retain the following
88 *    acknowledgment:
89 *    "This product includes software developed by the OpenSSL Project
90 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91 *
92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103 * OF THE POSSIBILITY OF SUCH DAMAGE.
104 * ====================================================================
105 *
106 * This product includes cryptographic software written by Eric Young
107 * (eay@cryptsoft.com).  This product includes software written by Tim
108 * Hudson (tjh@cryptsoft.com).
109 *
110 */
111
112
113#include "cryptlib.h"
114#include "bn_lcl.h"
115
116#define TABLE_SIZE	32
117
118/* this one works - simple but works */
119int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
120	{
121	int i,bits,ret=0;
122	BIGNUM *v,*rr;
123
124	BN_CTX_start(ctx);
125	if ((r == a) || (r == p))
126		rr = BN_CTX_get(ctx);
127	else
128		rr = r;
129	if ((v = BN_CTX_get(ctx)) == NULL) goto err;
130
131	if (BN_copy(v,a) == NULL) goto err;
132	bits=BN_num_bits(p);
133
134	if (BN_is_odd(p))
135		{ if (BN_copy(rr,a) == NULL) goto err; }
136	else	{ if (!BN_one(rr)) goto err; }
137
138	for (i=1; i<bits; i++)
139		{
140		if (!BN_sqr(v,v,ctx)) goto err;
141		if (BN_is_bit_set(p,i))
142			{
143			if (!BN_mul(rr,rr,v,ctx)) goto err;
144			}
145		}
146	ret=1;
147err:
148	if (r != rr) BN_copy(r,rr);
149	BN_CTX_end(ctx);
150	return(ret);
151	}
152
153
154int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
155	       BN_CTX *ctx)
156	{
157	int ret;
158
159	bn_check_top(a);
160	bn_check_top(p);
161	bn_check_top(m);
162
163	/* For even modulus  m = 2^k*m_odd,  it might make sense to compute
164	 * a^p mod m_odd  and  a^p mod 2^k  separately (with Montgomery
165	 * exponentiation for the odd part), using appropriate exponent
166	 * reductions, and combine the results using the CRT.
167	 *
168	 * For now, we use Montgomery only if the modulus is odd; otherwise,
169	 * exponentiation using the reciprocal-based quick remaindering
170	 * algorithm is used.
171	 *
172	 * (Timing obtained with expspeed.c [computations  a^p mod m
173	 * where  a, p, m  are of the same length: 256, 512, 1024, 2048,
174	 * 4096, 8192 bits], compared to the running time of the
175	 * standard algorithm:
176	 *
177	 *   BN_mod_exp_mont   33 .. 40 %  [AMD K6-2, Linux, debug configuration]
178         *                     55 .. 77 %  [UltraSparc processor, but
179	 *                                  debug-solaris-sparcv8-gcc conf.]
180	 *
181	 *   BN_mod_exp_recp   50 .. 70 %  [AMD K6-2, Linux, debug configuration]
182	 *                     62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]
183	 *
184	 * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont
185	 * at 2048 and more bits, but at 512 and 1024 bits, it was
186	 * slower even than the standard algorithm!
187	 *
188	 * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations]
189	 * should be obtained when the new Montgomery reduction code
190	 * has been integrated into OpenSSL.)
191	 */
192
193#define MONT_MUL_MOD
194#define MONT_EXP_WORD
195#define RECP_MUL_MOD
196
197#ifdef MONT_MUL_MOD
198	/* I have finally been able to take out this pre-condition of
199	 * the top bit being set.  It was caused by an error in BN_div
200	 * with negatives.  There was also another problem when for a^b%m
201	 * a >= m.  eay 07-May-97 */
202/*	if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */
203
204	if (BN_is_odd(m))
205		{
206#  ifdef MONT_EXP_WORD
207		if (a->top == 1 && !a->neg)
208			{
209			BN_ULONG A = a->d[0];
210			ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL);
211			}
212		else
213#  endif
214			ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL);
215		}
216	else
217#endif
218#ifdef RECP_MUL_MOD
219		{ ret=BN_mod_exp_recp(r,a,p,m,ctx); }
220#else
221		{ ret=BN_mod_exp_simple(r,a,p,m,ctx); }
222#endif
223
224	return(ret);
225	}
226
227
228int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
229		    const BIGNUM *m, BN_CTX *ctx)
230	{
231	int i,j,bits,ret=0,wstart,wend,window,wvalue;
232	int start=1,ts=0;
233	BIGNUM *aa;
234	BIGNUM val[TABLE_SIZE];
235	BN_RECP_CTX recp;
236
237	bits=BN_num_bits(p);
238
239	if (bits == 0)
240		{
241		ret = BN_one(r);
242		return ret;
243		}
244
245	BN_CTX_start(ctx);
246	if ((aa = BN_CTX_get(ctx)) == NULL) goto err;
247
248	BN_RECP_CTX_init(&recp);
249	if (m->neg)
250		{
251		/* ignore sign of 'm' */
252		if (!BN_copy(aa, m)) goto err;
253		aa->neg = 0;
254		if (BN_RECP_CTX_set(&recp,aa,ctx) <= 0) goto err;
255		}
256	else
257		{
258		if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
259		}
260
261	BN_init(&(val[0]));
262	ts=1;
263
264	if (!BN_nnmod(&(val[0]),a,m,ctx)) goto err;		/* 1 */
265	if (BN_is_zero(&(val[0])))
266		{
267		ret = BN_zero(r);
268		goto err;
269		}
270
271	window = BN_window_bits_for_exponent_size(bits);
272	if (window > 1)
273		{
274		if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx))
275			goto err;				/* 2 */
276		j=1<<(window-1);
277		for (i=1; i<j; i++)
278			{
279			BN_init(&val[i]);
280			if (!BN_mod_mul_reciprocal(&(val[i]),&(val[i-1]),aa,&recp,ctx))
281				goto err;
282			}
283		ts=i;
284		}
285
286	start=1;	/* This is used to avoid multiplication etc
287			 * when there is only the value '1' in the
288			 * buffer. */
289	wvalue=0;	/* The 'value' of the window */
290	wstart=bits-1;	/* The top bit of the window */
291	wend=0;		/* The bottom bit of the window */
292
293	if (!BN_one(r)) goto err;
294
295	for (;;)
296		{
297		if (BN_is_bit_set(p,wstart) == 0)
298			{
299			if (!start)
300				if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
301				goto err;
302			if (wstart == 0) break;
303			wstart--;
304			continue;
305			}
306		/* We now have wstart on a 'set' bit, we now need to work out
307		 * how bit a window to do.  To do this we need to scan
308		 * forward until the last set bit before the end of the
309		 * window */
310		j=wstart;
311		wvalue=1;
312		wend=0;
313		for (i=1; i<window; i++)
314			{
315			if (wstart-i < 0) break;
316			if (BN_is_bit_set(p,wstart-i))
317				{
318				wvalue<<=(i-wend);
319				wvalue|=1;
320				wend=i;
321				}
322			}
323
324		/* wend is the size of the current window */
325		j=wend+1;
326		/* add the 'bytes above' */
327		if (!start)
328			for (i=0; i<j; i++)
329				{
330				if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
331					goto err;
332				}
333
334		/* wvalue will be an odd number < 2^window */
335		if (!BN_mod_mul_reciprocal(r,r,&(val[wvalue>>1]),&recp,ctx))
336			goto err;
337
338		/* move the 'window' down further */
339		wstart-=wend+1;
340		wvalue=0;
341		start=0;
342		if (wstart < 0) break;
343		}
344	ret=1;
345err:
346	BN_CTX_end(ctx);
347	for (i=0; i<ts; i++)
348		BN_clear_free(&(val[i]));
349	BN_RECP_CTX_free(&recp);
350	return(ret);
351	}
352
353
354int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
355		    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
356	{
357	int i,j,bits,ret=0,wstart,wend,window,wvalue;
358	int start=1,ts=0;
359	BIGNUM *d,*r;
360	const BIGNUM *aa;
361	BIGNUM val[TABLE_SIZE];
362	BN_MONT_CTX *mont=NULL;
363
364	bn_check_top(a);
365	bn_check_top(p);
366	bn_check_top(m);
367
368	if (!(m->d[0] & 1))
369		{
370		BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS);
371		return(0);
372		}
373	bits=BN_num_bits(p);
374	if (bits == 0)
375		{
376		ret = BN_one(rr);
377		return ret;
378		}
379
380	BN_CTX_start(ctx);
381	d = BN_CTX_get(ctx);
382	r = BN_CTX_get(ctx);
383	if (d == NULL || r == NULL) goto err;
384
385	/* If this is not done, things will break in the montgomery
386	 * part */
387
388	if (in_mont != NULL)
389		mont=in_mont;
390	else
391		{
392		if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
393		if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
394		}
395
396	BN_init(&val[0]);
397	ts=1;
398	if (a->neg || BN_ucmp(a,m) >= 0)
399		{
400		if (!BN_nnmod(&(val[0]),a,m,ctx))
401			goto err;
402		aa= &(val[0]);
403		}
404	else
405		aa=a;
406	if (BN_is_zero(aa))
407		{
408		ret = BN_zero(rr);
409		goto err;
410		}
411	if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */
412
413	window = BN_window_bits_for_exponent_size(bits);
414	if (window > 1)
415		{
416		if (!BN_mod_mul_montgomery(d,&(val[0]),&(val[0]),mont,ctx)) goto err; /* 2 */
417		j=1<<(window-1);
418		for (i=1; i<j; i++)
419			{
420			BN_init(&(val[i]));
421			if (!BN_mod_mul_montgomery(&(val[i]),&(val[i-1]),d,mont,ctx))
422				goto err;
423			}
424		ts=i;
425		}
426
427	start=1;	/* This is used to avoid multiplication etc
428			 * when there is only the value '1' in the
429			 * buffer. */
430	wvalue=0;	/* The 'value' of the window */
431	wstart=bits-1;	/* The top bit of the window */
432	wend=0;		/* The bottom bit of the window */
433
434	if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
435	for (;;)
436		{
437		if (BN_is_bit_set(p,wstart) == 0)
438			{
439			if (!start)
440				{
441				if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
442				goto err;
443				}
444			if (wstart == 0) break;
445			wstart--;
446			continue;
447			}
448		/* We now have wstart on a 'set' bit, we now need to work out
449		 * how bit a window to do.  To do this we need to scan
450		 * forward until the last set bit before the end of the
451		 * window */
452		j=wstart;
453		wvalue=1;
454		wend=0;
455		for (i=1; i<window; i++)
456			{
457			if (wstart-i < 0) break;
458			if (BN_is_bit_set(p,wstart-i))
459				{
460				wvalue<<=(i-wend);
461				wvalue|=1;
462				wend=i;
463				}
464			}
465
466		/* wend is the size of the current window */
467		j=wend+1;
468		/* add the 'bytes above' */
469		if (!start)
470			for (i=0; i<j; i++)
471				{
472				if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
473					goto err;
474				}
475
476		/* wvalue will be an odd number < 2^window */
477		if (!BN_mod_mul_montgomery(r,r,&(val[wvalue>>1]),mont,ctx))
478			goto err;
479
480		/* move the 'window' down further */
481		wstart-=wend+1;
482		wvalue=0;
483		start=0;
484		if (wstart < 0) break;
485		}
486	if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
487	ret=1;
488err:
489	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
490	BN_CTX_end(ctx);
491	for (i=0; i<ts; i++)
492		BN_clear_free(&(val[i]));
493	return(ret);
494	}
495
496int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
497                         const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
498	{
499	BN_MONT_CTX *mont = NULL;
500	int b, bits, ret=0;
501	int r_is_one;
502	BN_ULONG w, next_w;
503	BIGNUM *d, *r, *t;
504	BIGNUM *swap_tmp;
505#define BN_MOD_MUL_WORD(r, w, m) \
506		(BN_mul_word(r, (w)) && \
507		(/* BN_ucmp(r, (m)) < 0 ? 1 :*/  \
508			(BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
509		/* BN_MOD_MUL_WORD is only used with 'w' large,
510		 * so the BN_ucmp test is probably more overhead
511		 * than always using BN_mod (which uses BN_copy if
512		 * a similar test returns true). */
513		/* We can use BN_mod and do not need BN_nnmod because our
514		 * accumulator is never negative (the result of BN_mod does
515		 * not depend on the sign of the modulus).
516		 */
517#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
518		(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
519
520	bn_check_top(p);
521	bn_check_top(m);
522
523	if (m->top == 0 || !(m->d[0] & 1))
524		{
525		BNerr(BN_F_BN_MOD_EXP_MONT_WORD,BN_R_CALLED_WITH_EVEN_MODULUS);
526		return(0);
527		}
528	if (m->top == 1)
529		a %= m->d[0]; /* make sure that 'a' is reduced */
530
531	bits = BN_num_bits(p);
532	if (bits == 0)
533		{
534		ret = BN_one(rr);
535		return ret;
536		}
537	if (a == 0)
538		{
539		ret = BN_zero(rr);
540		return ret;
541		}
542
543	BN_CTX_start(ctx);
544	d = BN_CTX_get(ctx);
545	r = BN_CTX_get(ctx);
546	t = BN_CTX_get(ctx);
547	if (d == NULL || r == NULL || t == NULL) goto err;
548
549	if (in_mont != NULL)
550		mont=in_mont;
551	else
552		{
553		if ((mont = BN_MONT_CTX_new()) == NULL) goto err;
554		if (!BN_MONT_CTX_set(mont, m, ctx)) goto err;
555		}
556
557	r_is_one = 1; /* except for Montgomery factor */
558
559	/* bits-1 >= 0 */
560
561	/* The result is accumulated in the product r*w. */
562	w = a; /* bit 'bits-1' of 'p' is always set */
563	for (b = bits-2; b >= 0; b--)
564		{
565		/* First, square r*w. */
566		next_w = w*w;
567		if ((next_w/w) != w) /* overflow */
568			{
569			if (r_is_one)
570				{
571				if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
572				r_is_one = 0;
573				}
574			else
575				{
576				if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
577				}
578			next_w = 1;
579			}
580		w = next_w;
581		if (!r_is_one)
582			{
583			if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) goto err;
584			}
585
586		/* Second, multiply r*w by 'a' if exponent bit is set. */
587		if (BN_is_bit_set(p, b))
588			{
589			next_w = w*a;
590			if ((next_w/a) != w) /* overflow */
591				{
592				if (r_is_one)
593					{
594					if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
595					r_is_one = 0;
596					}
597				else
598					{
599					if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
600					}
601				next_w = a;
602				}
603			w = next_w;
604			}
605		}
606
607	/* Finally, set r:=r*w. */
608	if (w != 1)
609		{
610		if (r_is_one)
611			{
612			if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
613			r_is_one = 0;
614			}
615		else
616			{
617			if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
618			}
619		}
620
621	if (r_is_one) /* can happen only if a == 1*/
622		{
623		if (!BN_one(rr)) goto err;
624		}
625	else
626		{
627		if (!BN_from_montgomery(rr, r, mont, ctx)) goto err;
628		}
629	ret = 1;
630err:
631	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
632	BN_CTX_end(ctx);
633	return(ret);
634	}
635
636
637/* The old fallback, simple version :-) */
638int BN_mod_exp_simple(BIGNUM *r,
639	const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
640	BN_CTX *ctx)
641	{
642	int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0;
643	int start=1;
644	BIGNUM *d;
645	BIGNUM val[TABLE_SIZE];
646
647	bits=BN_num_bits(p);
648
649	if (bits == 0)
650		{
651		ret = BN_one(r);
652		return ret;
653		}
654
655	BN_CTX_start(ctx);
656	if ((d = BN_CTX_get(ctx)) == NULL) goto err;
657
658	BN_init(&(val[0]));
659	ts=1;
660	if (!BN_nnmod(&(val[0]),a,m,ctx)) goto err;		/* 1 */
661	if (BN_is_zero(&(val[0])))
662		{
663		ret = BN_zero(r);
664		goto err;
665		}
666
667	window = BN_window_bits_for_exponent_size(bits);
668	if (window > 1)
669		{
670		if (!BN_mod_mul(d,&(val[0]),&(val[0]),m,ctx))
671			goto err;				/* 2 */
672		j=1<<(window-1);
673		for (i=1; i<j; i++)
674			{
675			BN_init(&(val[i]));
676			if (!BN_mod_mul(&(val[i]),&(val[i-1]),d,m,ctx))
677				goto err;
678			}
679		ts=i;
680		}
681
682	start=1;	/* This is used to avoid multiplication etc
683			 * when there is only the value '1' in the
684			 * buffer. */
685	wvalue=0;	/* The 'value' of the window */
686	wstart=bits-1;	/* The top bit of the window */
687	wend=0;		/* The bottom bit of the window */
688
689	if (!BN_one(r)) goto err;
690
691	for (;;)
692		{
693		if (BN_is_bit_set(p,wstart) == 0)
694			{
695			if (!start)
696				if (!BN_mod_mul(r,r,r,m,ctx))
697				goto err;
698			if (wstart == 0) break;
699			wstart--;
700			continue;
701			}
702		/* We now have wstart on a 'set' bit, we now need to work out
703		 * how bit a window to do.  To do this we need to scan
704		 * forward until the last set bit before the end of the
705		 * window */
706		j=wstart;
707		wvalue=1;
708		wend=0;
709		for (i=1; i<window; i++)
710			{
711			if (wstart-i < 0) break;
712			if (BN_is_bit_set(p,wstart-i))
713				{
714				wvalue<<=(i-wend);
715				wvalue|=1;
716				wend=i;
717				}
718			}
719
720		/* wend is the size of the current window */
721		j=wend+1;
722		/* add the 'bytes above' */
723		if (!start)
724			for (i=0; i<j; i++)
725				{
726				if (!BN_mod_mul(r,r,r,m,ctx))
727					goto err;
728				}
729
730		/* wvalue will be an odd number < 2^window */
731		if (!BN_mod_mul(r,r,&(val[wvalue>>1]),m,ctx))
732			goto err;
733
734		/* move the 'window' down further */
735		wstart-=wend+1;
736		wvalue=0;
737		start=0;
738		if (wstart < 0) break;
739		}
740	ret=1;
741err:
742	BN_CTX_end(ctx);
743	for (i=0; i<ts; i++)
744		BN_clear_free(&(val[i]));
745	return(ret);
746	}
747
748