xref: /titanic_53/usr/src/common/mpi/mpi.c (revision f9fbec18f5b458b560ecf45d3db8e8bd56bf6942)
1*f9fbec18Smcpowers /*
2*f9fbec18Smcpowers  *  mpi.c
3*f9fbec18Smcpowers  *
4*f9fbec18Smcpowers  *  Arbitrary precision integer arithmetic library
5*f9fbec18Smcpowers  *
6*f9fbec18Smcpowers  * ***** BEGIN LICENSE BLOCK *****
7*f9fbec18Smcpowers  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
8*f9fbec18Smcpowers  *
9*f9fbec18Smcpowers  * The contents of this file are subject to the Mozilla Public License Version
10*f9fbec18Smcpowers  * 1.1 (the "License"); you may not use this file except in compliance with
11*f9fbec18Smcpowers  * the License. You may obtain a copy of the License at
12*f9fbec18Smcpowers  * http://www.mozilla.org/MPL/
13*f9fbec18Smcpowers  *
14*f9fbec18Smcpowers  * Software distributed under the License is distributed on an "AS IS" basis,
15*f9fbec18Smcpowers  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16*f9fbec18Smcpowers  * for the specific language governing rights and limitations under the
17*f9fbec18Smcpowers  * License.
18*f9fbec18Smcpowers  *
19*f9fbec18Smcpowers  * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
20*f9fbec18Smcpowers  *
21*f9fbec18Smcpowers  * The Initial Developer of the Original Code is
22*f9fbec18Smcpowers  * Michael J. Fromberger.
23*f9fbec18Smcpowers  * Portions created by the Initial Developer are Copyright (C) 1998
24*f9fbec18Smcpowers  * the Initial Developer. All Rights Reserved.
25*f9fbec18Smcpowers  *
26*f9fbec18Smcpowers  * Contributor(s):
27*f9fbec18Smcpowers  *   Netscape Communications Corporation
28*f9fbec18Smcpowers  *   Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
29*f9fbec18Smcpowers  *
30*f9fbec18Smcpowers  * Alternatively, the contents of this file may be used under the terms of
31*f9fbec18Smcpowers  * either the GNU General Public License Version 2 or later (the "GPL"), or
32*f9fbec18Smcpowers  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33*f9fbec18Smcpowers  * in which case the provisions of the GPL or the LGPL are applicable instead
34*f9fbec18Smcpowers  * of those above. If you wish to allow use of your version of this file only
35*f9fbec18Smcpowers  * under the terms of either the GPL or the LGPL, and not to allow others to
36*f9fbec18Smcpowers  * use your version of this file under the terms of the MPL, indicate your
37*f9fbec18Smcpowers  * decision by deleting the provisions above and replace them with the notice
38*f9fbec18Smcpowers  * and other provisions required by the GPL or the LGPL. If you do not delete
39*f9fbec18Smcpowers  * the provisions above, a recipient may use your version of this file under
40*f9fbec18Smcpowers  * the terms of any one of the MPL, the GPL or the LGPL.
41*f9fbec18Smcpowers  *
42*f9fbec18Smcpowers  * ***** END LICENSE BLOCK ***** */
43*f9fbec18Smcpowers /*
44*f9fbec18Smcpowers  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
45*f9fbec18Smcpowers  * Use is subject to license terms.
46*f9fbec18Smcpowers  *
47*f9fbec18Smcpowers  * Sun elects to use this software under the MPL license.
48*f9fbec18Smcpowers  */
49*f9fbec18Smcpowers 
50*f9fbec18Smcpowers #pragma ident	"%Z%%M%	%I%	%E% SMI"
51*f9fbec18Smcpowers 
52*f9fbec18Smcpowers /* $Id: mpi.c,v 1.45 2006/09/29 20:12:21 alexei.volkov.bugs%sun.com Exp $ */
53*f9fbec18Smcpowers 
54*f9fbec18Smcpowers #include "mpi-priv.h"
55*f9fbec18Smcpowers #if defined(OSF1)
56*f9fbec18Smcpowers #include <c_asm.h>
57*f9fbec18Smcpowers #endif
58*f9fbec18Smcpowers 
59*f9fbec18Smcpowers #if MP_LOGTAB
60*f9fbec18Smcpowers /*
61*f9fbec18Smcpowers   A table of the logs of 2 for various bases (the 0 and 1 entries of
62*f9fbec18Smcpowers   this table are meaningless and should not be referenced).
63*f9fbec18Smcpowers 
64*f9fbec18Smcpowers   This table is used to compute output lengths for the mp_toradix()
65*f9fbec18Smcpowers   function.  Since a number n in radix r takes up about log_r(n)
66*f9fbec18Smcpowers   digits, we estimate the output size by taking the least integer
67*f9fbec18Smcpowers   greater than log_r(n), where:
68*f9fbec18Smcpowers 
69*f9fbec18Smcpowers   log_r(n) = log_2(n) * log_r(2)
70*f9fbec18Smcpowers 
71*f9fbec18Smcpowers   This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
72*f9fbec18Smcpowers   which are the output bases supported.
73*f9fbec18Smcpowers  */
74*f9fbec18Smcpowers #include "logtab.h"
75*f9fbec18Smcpowers #endif
76*f9fbec18Smcpowers 
77*f9fbec18Smcpowers /* {{{ Constant strings */
78*f9fbec18Smcpowers 
79*f9fbec18Smcpowers /* Constant strings returned by mp_strerror() */
80*f9fbec18Smcpowers static const char *mp_err_string[] = {
81*f9fbec18Smcpowers   "unknown result code",     /* say what?            */
82*f9fbec18Smcpowers   "boolean true",            /* MP_OKAY, MP_YES      */
83*f9fbec18Smcpowers   "boolean false",           /* MP_NO                */
84*f9fbec18Smcpowers   "out of memory",           /* MP_MEM               */
85*f9fbec18Smcpowers   "argument out of range",   /* MP_RANGE             */
86*f9fbec18Smcpowers   "invalid input parameter", /* MP_BADARG            */
87*f9fbec18Smcpowers   "result is undefined"      /* MP_UNDEF             */
88*f9fbec18Smcpowers };
89*f9fbec18Smcpowers 
90*f9fbec18Smcpowers /* Value to digit maps for radix conversion   */
91*f9fbec18Smcpowers 
92*f9fbec18Smcpowers /* s_dmap_1 - standard digits and letters */
93*f9fbec18Smcpowers static const char *s_dmap_1 =
94*f9fbec18Smcpowers   "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
95*f9fbec18Smcpowers 
96*f9fbec18Smcpowers /* }}} */
97*f9fbec18Smcpowers 
98*f9fbec18Smcpowers unsigned long mp_allocs;
99*f9fbec18Smcpowers unsigned long mp_frees;
100*f9fbec18Smcpowers unsigned long mp_copies;
101*f9fbec18Smcpowers 
102*f9fbec18Smcpowers /* {{{ Default precision manipulation */
103*f9fbec18Smcpowers 
104*f9fbec18Smcpowers /* Default precision for newly created mp_int's      */
105*f9fbec18Smcpowers static mp_size s_mp_defprec = MP_DEFPREC;
106*f9fbec18Smcpowers 
107*f9fbec18Smcpowers mp_size mp_get_prec(void)
108*f9fbec18Smcpowers {
109*f9fbec18Smcpowers   return s_mp_defprec;
110*f9fbec18Smcpowers 
111*f9fbec18Smcpowers } /* end mp_get_prec() */
112*f9fbec18Smcpowers 
113*f9fbec18Smcpowers void         mp_set_prec(mp_size prec)
114*f9fbec18Smcpowers {
115*f9fbec18Smcpowers   if(prec == 0)
116*f9fbec18Smcpowers     s_mp_defprec = MP_DEFPREC;
117*f9fbec18Smcpowers   else
118*f9fbec18Smcpowers     s_mp_defprec = prec;
119*f9fbec18Smcpowers 
120*f9fbec18Smcpowers } /* end mp_set_prec() */
121*f9fbec18Smcpowers 
122*f9fbec18Smcpowers /* }}} */
123*f9fbec18Smcpowers 
124*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
125*f9fbec18Smcpowers /* {{{ mp_init(mp, kmflag) */
126*f9fbec18Smcpowers 
127*f9fbec18Smcpowers /*
128*f9fbec18Smcpowers   mp_init(mp, kmflag)
129*f9fbec18Smcpowers 
130*f9fbec18Smcpowers   Initialize a new zero-valued mp_int.  Returns MP_OKAY if successful,
131*f9fbec18Smcpowers   MP_MEM if memory could not be allocated for the structure.
132*f9fbec18Smcpowers  */
133*f9fbec18Smcpowers 
134*f9fbec18Smcpowers mp_err mp_init(mp_int *mp, int kmflag)
135*f9fbec18Smcpowers {
136*f9fbec18Smcpowers   return mp_init_size(mp, s_mp_defprec, kmflag);
137*f9fbec18Smcpowers 
138*f9fbec18Smcpowers } /* end mp_init() */
139*f9fbec18Smcpowers 
140*f9fbec18Smcpowers /* }}} */
141*f9fbec18Smcpowers 
142*f9fbec18Smcpowers /* {{{ mp_init_size(mp, prec, kmflag) */
143*f9fbec18Smcpowers 
144*f9fbec18Smcpowers /*
145*f9fbec18Smcpowers   mp_init_size(mp, prec, kmflag)
146*f9fbec18Smcpowers 
147*f9fbec18Smcpowers   Initialize a new zero-valued mp_int with at least the given
148*f9fbec18Smcpowers   precision; returns MP_OKAY if successful, or MP_MEM if memory could
149*f9fbec18Smcpowers   not be allocated for the structure.
150*f9fbec18Smcpowers  */
151*f9fbec18Smcpowers 
152*f9fbec18Smcpowers mp_err mp_init_size(mp_int *mp, mp_size prec, int kmflag)
153*f9fbec18Smcpowers {
154*f9fbec18Smcpowers   ARGCHK(mp != NULL && prec > 0, MP_BADARG);
155*f9fbec18Smcpowers 
156*f9fbec18Smcpowers   prec = MP_ROUNDUP(prec, s_mp_defprec);
157*f9fbec18Smcpowers   if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit), kmflag)) == NULL)
158*f9fbec18Smcpowers     return MP_MEM;
159*f9fbec18Smcpowers 
160*f9fbec18Smcpowers   SIGN(mp) = ZPOS;
161*f9fbec18Smcpowers   USED(mp) = 1;
162*f9fbec18Smcpowers   ALLOC(mp) = prec;
163*f9fbec18Smcpowers 
164*f9fbec18Smcpowers   return MP_OKAY;
165*f9fbec18Smcpowers 
166*f9fbec18Smcpowers } /* end mp_init_size() */
167*f9fbec18Smcpowers 
168*f9fbec18Smcpowers /* }}} */
169*f9fbec18Smcpowers 
170*f9fbec18Smcpowers /* {{{ mp_init_copy(mp, from) */
171*f9fbec18Smcpowers 
172*f9fbec18Smcpowers /*
173*f9fbec18Smcpowers   mp_init_copy(mp, from)
174*f9fbec18Smcpowers 
175*f9fbec18Smcpowers   Initialize mp as an exact copy of from.  Returns MP_OKAY if
176*f9fbec18Smcpowers   successful, MP_MEM if memory could not be allocated for the new
177*f9fbec18Smcpowers   structure.
178*f9fbec18Smcpowers  */
179*f9fbec18Smcpowers 
180*f9fbec18Smcpowers mp_err mp_init_copy(mp_int *mp, const mp_int *from)
181*f9fbec18Smcpowers {
182*f9fbec18Smcpowers   ARGCHK(mp != NULL && from != NULL, MP_BADARG);
183*f9fbec18Smcpowers 
184*f9fbec18Smcpowers   if(mp == from)
185*f9fbec18Smcpowers     return MP_OKAY;
186*f9fbec18Smcpowers 
187*f9fbec18Smcpowers   if((DIGITS(mp) = s_mp_alloc(ALLOC(from), sizeof(mp_digit), FLAG(from))) == NULL)
188*f9fbec18Smcpowers     return MP_MEM;
189*f9fbec18Smcpowers 
190*f9fbec18Smcpowers   s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));
191*f9fbec18Smcpowers   USED(mp) = USED(from);
192*f9fbec18Smcpowers   ALLOC(mp) = ALLOC(from);
193*f9fbec18Smcpowers   SIGN(mp) = SIGN(from);
194*f9fbec18Smcpowers   FLAG(mp) = FLAG(from);
195*f9fbec18Smcpowers 
196*f9fbec18Smcpowers   return MP_OKAY;
197*f9fbec18Smcpowers 
198*f9fbec18Smcpowers } /* end mp_init_copy() */
199*f9fbec18Smcpowers 
200*f9fbec18Smcpowers /* }}} */
201*f9fbec18Smcpowers 
202*f9fbec18Smcpowers /* {{{ mp_copy(from, to) */
203*f9fbec18Smcpowers 
204*f9fbec18Smcpowers /*
205*f9fbec18Smcpowers   mp_copy(from, to)
206*f9fbec18Smcpowers 
207*f9fbec18Smcpowers   Copies the mp_int 'from' to the mp_int 'to'.  It is presumed that
208*f9fbec18Smcpowers   'to' has already been initialized (if not, use mp_init_copy()
209*f9fbec18Smcpowers   instead). If 'from' and 'to' are identical, nothing happens.
210*f9fbec18Smcpowers  */
211*f9fbec18Smcpowers 
212*f9fbec18Smcpowers mp_err mp_copy(const mp_int *from, mp_int *to)
213*f9fbec18Smcpowers {
214*f9fbec18Smcpowers   ARGCHK(from != NULL && to != NULL, MP_BADARG);
215*f9fbec18Smcpowers 
216*f9fbec18Smcpowers   if(from == to)
217*f9fbec18Smcpowers     return MP_OKAY;
218*f9fbec18Smcpowers 
219*f9fbec18Smcpowers   ++mp_copies;
220*f9fbec18Smcpowers   { /* copy */
221*f9fbec18Smcpowers     mp_digit   *tmp;
222*f9fbec18Smcpowers 
223*f9fbec18Smcpowers     /*
224*f9fbec18Smcpowers       If the allocated buffer in 'to' already has enough space to hold
225*f9fbec18Smcpowers       all the used digits of 'from', we'll re-use it to avoid hitting
226*f9fbec18Smcpowers       the memory allocater more than necessary; otherwise, we'd have
227*f9fbec18Smcpowers       to grow anyway, so we just allocate a hunk and make the copy as
228*f9fbec18Smcpowers       usual
229*f9fbec18Smcpowers      */
230*f9fbec18Smcpowers     if(ALLOC(to) >= USED(from)) {
231*f9fbec18Smcpowers       s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));
232*f9fbec18Smcpowers       s_mp_copy(DIGITS(from), DIGITS(to), USED(from));
233*f9fbec18Smcpowers 
234*f9fbec18Smcpowers     } else {
235*f9fbec18Smcpowers       if((tmp = s_mp_alloc(ALLOC(from), sizeof(mp_digit), FLAG(from))) == NULL)
236*f9fbec18Smcpowers 	return MP_MEM;
237*f9fbec18Smcpowers 
238*f9fbec18Smcpowers       s_mp_copy(DIGITS(from), tmp, USED(from));
239*f9fbec18Smcpowers 
240*f9fbec18Smcpowers       if(DIGITS(to) != NULL) {
241*f9fbec18Smcpowers #if MP_CRYPTO
242*f9fbec18Smcpowers 	s_mp_setz(DIGITS(to), ALLOC(to));
243*f9fbec18Smcpowers #endif
244*f9fbec18Smcpowers 	s_mp_free(DIGITS(to), ALLOC(to));
245*f9fbec18Smcpowers       }
246*f9fbec18Smcpowers 
247*f9fbec18Smcpowers       DIGITS(to) = tmp;
248*f9fbec18Smcpowers       ALLOC(to) = ALLOC(from);
249*f9fbec18Smcpowers     }
250*f9fbec18Smcpowers 
251*f9fbec18Smcpowers     /* Copy the precision and sign from the original */
252*f9fbec18Smcpowers     USED(to) = USED(from);
253*f9fbec18Smcpowers     SIGN(to) = SIGN(from);
254*f9fbec18Smcpowers   } /* end copy */
255*f9fbec18Smcpowers 
256*f9fbec18Smcpowers   return MP_OKAY;
257*f9fbec18Smcpowers 
258*f9fbec18Smcpowers } /* end mp_copy() */
259*f9fbec18Smcpowers 
260*f9fbec18Smcpowers /* }}} */
261*f9fbec18Smcpowers 
262*f9fbec18Smcpowers /* {{{ mp_exch(mp1, mp2) */
263*f9fbec18Smcpowers 
264*f9fbec18Smcpowers /*
265*f9fbec18Smcpowers   mp_exch(mp1, mp2)
266*f9fbec18Smcpowers 
267*f9fbec18Smcpowers   Exchange mp1 and mp2 without allocating any intermediate memory
268*f9fbec18Smcpowers   (well, unless you count the stack space needed for this call and the
269*f9fbec18Smcpowers   locals it creates...).  This cannot fail.
270*f9fbec18Smcpowers  */
271*f9fbec18Smcpowers 
272*f9fbec18Smcpowers void mp_exch(mp_int *mp1, mp_int *mp2)
273*f9fbec18Smcpowers {
274*f9fbec18Smcpowers #if MP_ARGCHK == 2
275*f9fbec18Smcpowers   assert(mp1 != NULL && mp2 != NULL);
276*f9fbec18Smcpowers #else
277*f9fbec18Smcpowers   if(mp1 == NULL || mp2 == NULL)
278*f9fbec18Smcpowers     return;
279*f9fbec18Smcpowers #endif
280*f9fbec18Smcpowers 
281*f9fbec18Smcpowers   s_mp_exch(mp1, mp2);
282*f9fbec18Smcpowers 
283*f9fbec18Smcpowers } /* end mp_exch() */
284*f9fbec18Smcpowers 
285*f9fbec18Smcpowers /* }}} */
286*f9fbec18Smcpowers 
287*f9fbec18Smcpowers /* {{{ mp_clear(mp) */
288*f9fbec18Smcpowers 
289*f9fbec18Smcpowers /*
290*f9fbec18Smcpowers   mp_clear(mp)
291*f9fbec18Smcpowers 
292*f9fbec18Smcpowers   Release the storage used by an mp_int, and void its fields so that
293*f9fbec18Smcpowers   if someone calls mp_clear() again for the same int later, we won't
294*f9fbec18Smcpowers   get tollchocked.
295*f9fbec18Smcpowers  */
296*f9fbec18Smcpowers 
297*f9fbec18Smcpowers void   mp_clear(mp_int *mp)
298*f9fbec18Smcpowers {
299*f9fbec18Smcpowers   if(mp == NULL)
300*f9fbec18Smcpowers     return;
301*f9fbec18Smcpowers 
302*f9fbec18Smcpowers   if(DIGITS(mp) != NULL) {
303*f9fbec18Smcpowers #if MP_CRYPTO
304*f9fbec18Smcpowers     s_mp_setz(DIGITS(mp), ALLOC(mp));
305*f9fbec18Smcpowers #endif
306*f9fbec18Smcpowers     s_mp_free(DIGITS(mp), ALLOC(mp));
307*f9fbec18Smcpowers     DIGITS(mp) = NULL;
308*f9fbec18Smcpowers   }
309*f9fbec18Smcpowers 
310*f9fbec18Smcpowers   USED(mp) = 0;
311*f9fbec18Smcpowers   ALLOC(mp) = 0;
312*f9fbec18Smcpowers 
313*f9fbec18Smcpowers } /* end mp_clear() */
314*f9fbec18Smcpowers 
315*f9fbec18Smcpowers /* }}} */
316*f9fbec18Smcpowers 
317*f9fbec18Smcpowers /* {{{ mp_zero(mp) */
318*f9fbec18Smcpowers 
319*f9fbec18Smcpowers /*
320*f9fbec18Smcpowers   mp_zero(mp)
321*f9fbec18Smcpowers 
322*f9fbec18Smcpowers   Set mp to zero.  Does not change the allocated size of the structure,
323*f9fbec18Smcpowers   and therefore cannot fail (except on a bad argument, which we ignore)
324*f9fbec18Smcpowers  */
325*f9fbec18Smcpowers void   mp_zero(mp_int *mp)
326*f9fbec18Smcpowers {
327*f9fbec18Smcpowers   if(mp == NULL)
328*f9fbec18Smcpowers     return;
329*f9fbec18Smcpowers 
330*f9fbec18Smcpowers   s_mp_setz(DIGITS(mp), ALLOC(mp));
331*f9fbec18Smcpowers   USED(mp) = 1;
332*f9fbec18Smcpowers   SIGN(mp) = ZPOS;
333*f9fbec18Smcpowers 
334*f9fbec18Smcpowers } /* end mp_zero() */
335*f9fbec18Smcpowers 
336*f9fbec18Smcpowers /* }}} */
337*f9fbec18Smcpowers 
338*f9fbec18Smcpowers /* {{{ mp_set(mp, d) */
339*f9fbec18Smcpowers 
340*f9fbec18Smcpowers void   mp_set(mp_int *mp, mp_digit d)
341*f9fbec18Smcpowers {
342*f9fbec18Smcpowers   if(mp == NULL)
343*f9fbec18Smcpowers     return;
344*f9fbec18Smcpowers 
345*f9fbec18Smcpowers   mp_zero(mp);
346*f9fbec18Smcpowers   DIGIT(mp, 0) = d;
347*f9fbec18Smcpowers 
348*f9fbec18Smcpowers } /* end mp_set() */
349*f9fbec18Smcpowers 
350*f9fbec18Smcpowers /* }}} */
351*f9fbec18Smcpowers 
352*f9fbec18Smcpowers /* {{{ mp_set_int(mp, z) */
353*f9fbec18Smcpowers 
354*f9fbec18Smcpowers mp_err mp_set_int(mp_int *mp, long z)
355*f9fbec18Smcpowers {
356*f9fbec18Smcpowers   int            ix;
357*f9fbec18Smcpowers   unsigned long  v = labs(z);
358*f9fbec18Smcpowers   mp_err         res;
359*f9fbec18Smcpowers 
360*f9fbec18Smcpowers   ARGCHK(mp != NULL, MP_BADARG);
361*f9fbec18Smcpowers 
362*f9fbec18Smcpowers   mp_zero(mp);
363*f9fbec18Smcpowers   if(z == 0)
364*f9fbec18Smcpowers     return MP_OKAY;  /* shortcut for zero */
365*f9fbec18Smcpowers 
366*f9fbec18Smcpowers   if (sizeof v <= sizeof(mp_digit)) {
367*f9fbec18Smcpowers     DIGIT(mp,0) = v;
368*f9fbec18Smcpowers   } else {
369*f9fbec18Smcpowers     for (ix = sizeof(long) - 1; ix >= 0; ix--) {
370*f9fbec18Smcpowers       if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
371*f9fbec18Smcpowers 	return res;
372*f9fbec18Smcpowers 
373*f9fbec18Smcpowers       res = s_mp_add_d(mp, (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
374*f9fbec18Smcpowers       if (res != MP_OKAY)
375*f9fbec18Smcpowers 	return res;
376*f9fbec18Smcpowers     }
377*f9fbec18Smcpowers   }
378*f9fbec18Smcpowers   if(z < 0)
379*f9fbec18Smcpowers     SIGN(mp) = NEG;
380*f9fbec18Smcpowers 
381*f9fbec18Smcpowers   return MP_OKAY;
382*f9fbec18Smcpowers 
383*f9fbec18Smcpowers } /* end mp_set_int() */
384*f9fbec18Smcpowers 
385*f9fbec18Smcpowers /* }}} */
386*f9fbec18Smcpowers 
387*f9fbec18Smcpowers /* {{{ mp_set_ulong(mp, z) */
388*f9fbec18Smcpowers 
389*f9fbec18Smcpowers mp_err mp_set_ulong(mp_int *mp, unsigned long z)
390*f9fbec18Smcpowers {
391*f9fbec18Smcpowers   int            ix;
392*f9fbec18Smcpowers   mp_err         res;
393*f9fbec18Smcpowers 
394*f9fbec18Smcpowers   ARGCHK(mp != NULL, MP_BADARG);
395*f9fbec18Smcpowers 
396*f9fbec18Smcpowers   mp_zero(mp);
397*f9fbec18Smcpowers   if(z == 0)
398*f9fbec18Smcpowers     return MP_OKAY;  /* shortcut for zero */
399*f9fbec18Smcpowers 
400*f9fbec18Smcpowers   if (sizeof z <= sizeof(mp_digit)) {
401*f9fbec18Smcpowers     DIGIT(mp,0) = z;
402*f9fbec18Smcpowers   } else {
403*f9fbec18Smcpowers     for (ix = sizeof(long) - 1; ix >= 0; ix--) {
404*f9fbec18Smcpowers       if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
405*f9fbec18Smcpowers 	return res;
406*f9fbec18Smcpowers 
407*f9fbec18Smcpowers       res = s_mp_add_d(mp, (mp_digit)((z >> (ix * CHAR_BIT)) & UCHAR_MAX));
408*f9fbec18Smcpowers       if (res != MP_OKAY)
409*f9fbec18Smcpowers 	return res;
410*f9fbec18Smcpowers     }
411*f9fbec18Smcpowers   }
412*f9fbec18Smcpowers   return MP_OKAY;
413*f9fbec18Smcpowers } /* end mp_set_ulong() */
414*f9fbec18Smcpowers 
415*f9fbec18Smcpowers /* }}} */
416*f9fbec18Smcpowers 
417*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
418*f9fbec18Smcpowers /* {{{ Digit arithmetic */
419*f9fbec18Smcpowers 
420*f9fbec18Smcpowers /* {{{ mp_add_d(a, d, b) */
421*f9fbec18Smcpowers 
422*f9fbec18Smcpowers /*
423*f9fbec18Smcpowers   mp_add_d(a, d, b)
424*f9fbec18Smcpowers 
425*f9fbec18Smcpowers   Compute the sum b = a + d, for a single digit d.  Respects the sign of
426*f9fbec18Smcpowers   its primary addend (single digits are unsigned anyway).
427*f9fbec18Smcpowers  */
428*f9fbec18Smcpowers 
429*f9fbec18Smcpowers mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b)
430*f9fbec18Smcpowers {
431*f9fbec18Smcpowers   mp_int   tmp;
432*f9fbec18Smcpowers   mp_err   res;
433*f9fbec18Smcpowers 
434*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
435*f9fbec18Smcpowers 
436*f9fbec18Smcpowers   if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
437*f9fbec18Smcpowers     return res;
438*f9fbec18Smcpowers 
439*f9fbec18Smcpowers   if(SIGN(&tmp) == ZPOS) {
440*f9fbec18Smcpowers     if((res = s_mp_add_d(&tmp, d)) != MP_OKAY)
441*f9fbec18Smcpowers       goto CLEANUP;
442*f9fbec18Smcpowers   } else if(s_mp_cmp_d(&tmp, d) >= 0) {
443*f9fbec18Smcpowers     if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY)
444*f9fbec18Smcpowers       goto CLEANUP;
445*f9fbec18Smcpowers   } else {
446*f9fbec18Smcpowers     mp_neg(&tmp, &tmp);
447*f9fbec18Smcpowers 
448*f9fbec18Smcpowers     DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0);
449*f9fbec18Smcpowers   }
450*f9fbec18Smcpowers 
451*f9fbec18Smcpowers   if(s_mp_cmp_d(&tmp, 0) == 0)
452*f9fbec18Smcpowers     SIGN(&tmp) = ZPOS;
453*f9fbec18Smcpowers 
454*f9fbec18Smcpowers   s_mp_exch(&tmp, b);
455*f9fbec18Smcpowers 
456*f9fbec18Smcpowers CLEANUP:
457*f9fbec18Smcpowers   mp_clear(&tmp);
458*f9fbec18Smcpowers   return res;
459*f9fbec18Smcpowers 
460*f9fbec18Smcpowers } /* end mp_add_d() */
461*f9fbec18Smcpowers 
462*f9fbec18Smcpowers /* }}} */
463*f9fbec18Smcpowers 
464*f9fbec18Smcpowers /* {{{ mp_sub_d(a, d, b) */
465*f9fbec18Smcpowers 
466*f9fbec18Smcpowers /*
467*f9fbec18Smcpowers   mp_sub_d(a, d, b)
468*f9fbec18Smcpowers 
469*f9fbec18Smcpowers   Compute the difference b = a - d, for a single digit d.  Respects the
470*f9fbec18Smcpowers   sign of its subtrahend (single digits are unsigned anyway).
471*f9fbec18Smcpowers  */
472*f9fbec18Smcpowers 
473*f9fbec18Smcpowers mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b)
474*f9fbec18Smcpowers {
475*f9fbec18Smcpowers   mp_int   tmp;
476*f9fbec18Smcpowers   mp_err   res;
477*f9fbec18Smcpowers 
478*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
479*f9fbec18Smcpowers 
480*f9fbec18Smcpowers   if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
481*f9fbec18Smcpowers     return res;
482*f9fbec18Smcpowers 
483*f9fbec18Smcpowers   if(SIGN(&tmp) == NEG) {
484*f9fbec18Smcpowers     if((res = s_mp_add_d(&tmp, d)) != MP_OKAY)
485*f9fbec18Smcpowers       goto CLEANUP;
486*f9fbec18Smcpowers   } else if(s_mp_cmp_d(&tmp, d) >= 0) {
487*f9fbec18Smcpowers     if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY)
488*f9fbec18Smcpowers       goto CLEANUP;
489*f9fbec18Smcpowers   } else {
490*f9fbec18Smcpowers     mp_neg(&tmp, &tmp);
491*f9fbec18Smcpowers 
492*f9fbec18Smcpowers     DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0);
493*f9fbec18Smcpowers     SIGN(&tmp) = NEG;
494*f9fbec18Smcpowers   }
495*f9fbec18Smcpowers 
496*f9fbec18Smcpowers   if(s_mp_cmp_d(&tmp, 0) == 0)
497*f9fbec18Smcpowers     SIGN(&tmp) = ZPOS;
498*f9fbec18Smcpowers 
499*f9fbec18Smcpowers   s_mp_exch(&tmp, b);
500*f9fbec18Smcpowers 
501*f9fbec18Smcpowers CLEANUP:
502*f9fbec18Smcpowers   mp_clear(&tmp);
503*f9fbec18Smcpowers   return res;
504*f9fbec18Smcpowers 
505*f9fbec18Smcpowers } /* end mp_sub_d() */
506*f9fbec18Smcpowers 
507*f9fbec18Smcpowers /* }}} */
508*f9fbec18Smcpowers 
509*f9fbec18Smcpowers /* {{{ mp_mul_d(a, d, b) */
510*f9fbec18Smcpowers 
511*f9fbec18Smcpowers /*
512*f9fbec18Smcpowers   mp_mul_d(a, d, b)
513*f9fbec18Smcpowers 
514*f9fbec18Smcpowers   Compute the product b = a * d, for a single digit d.  Respects the sign
515*f9fbec18Smcpowers   of its multiplicand (single digits are unsigned anyway)
516*f9fbec18Smcpowers  */
517*f9fbec18Smcpowers 
518*f9fbec18Smcpowers mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b)
519*f9fbec18Smcpowers {
520*f9fbec18Smcpowers   mp_err  res;
521*f9fbec18Smcpowers 
522*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
523*f9fbec18Smcpowers 
524*f9fbec18Smcpowers   if(d == 0) {
525*f9fbec18Smcpowers     mp_zero(b);
526*f9fbec18Smcpowers     return MP_OKAY;
527*f9fbec18Smcpowers   }
528*f9fbec18Smcpowers 
529*f9fbec18Smcpowers   if((res = mp_copy(a, b)) != MP_OKAY)
530*f9fbec18Smcpowers     return res;
531*f9fbec18Smcpowers 
532*f9fbec18Smcpowers   res = s_mp_mul_d(b, d);
533*f9fbec18Smcpowers 
534*f9fbec18Smcpowers   return res;
535*f9fbec18Smcpowers 
536*f9fbec18Smcpowers } /* end mp_mul_d() */
537*f9fbec18Smcpowers 
538*f9fbec18Smcpowers /* }}} */
539*f9fbec18Smcpowers 
540*f9fbec18Smcpowers /* {{{ mp_mul_2(a, c) */
541*f9fbec18Smcpowers 
542*f9fbec18Smcpowers mp_err mp_mul_2(const mp_int *a, mp_int *c)
543*f9fbec18Smcpowers {
544*f9fbec18Smcpowers   mp_err  res;
545*f9fbec18Smcpowers 
546*f9fbec18Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
547*f9fbec18Smcpowers 
548*f9fbec18Smcpowers   if((res = mp_copy(a, c)) != MP_OKAY)
549*f9fbec18Smcpowers     return res;
550*f9fbec18Smcpowers 
551*f9fbec18Smcpowers   return s_mp_mul_2(c);
552*f9fbec18Smcpowers 
553*f9fbec18Smcpowers } /* end mp_mul_2() */
554*f9fbec18Smcpowers 
555*f9fbec18Smcpowers /* }}} */
556*f9fbec18Smcpowers 
557*f9fbec18Smcpowers /* {{{ mp_div_d(a, d, q, r) */
558*f9fbec18Smcpowers 
559*f9fbec18Smcpowers /*
560*f9fbec18Smcpowers   mp_div_d(a, d, q, r)
561*f9fbec18Smcpowers 
562*f9fbec18Smcpowers   Compute the quotient q = a / d and remainder r = a mod d, for a
563*f9fbec18Smcpowers   single digit d.  Respects the sign of its divisor (single digits are
564*f9fbec18Smcpowers   unsigned anyway).
565*f9fbec18Smcpowers  */
566*f9fbec18Smcpowers 
567*f9fbec18Smcpowers mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
568*f9fbec18Smcpowers {
569*f9fbec18Smcpowers   mp_err   res;
570*f9fbec18Smcpowers   mp_int   qp;
571*f9fbec18Smcpowers   mp_digit rem;
572*f9fbec18Smcpowers   int      pow;
573*f9fbec18Smcpowers 
574*f9fbec18Smcpowers   ARGCHK(a != NULL, MP_BADARG);
575*f9fbec18Smcpowers 
576*f9fbec18Smcpowers   if(d == 0)
577*f9fbec18Smcpowers     return MP_RANGE;
578*f9fbec18Smcpowers 
579*f9fbec18Smcpowers   /* Shortcut for powers of two ... */
580*f9fbec18Smcpowers   if((pow = s_mp_ispow2d(d)) >= 0) {
581*f9fbec18Smcpowers     mp_digit  mask;
582*f9fbec18Smcpowers 
583*f9fbec18Smcpowers     mask = ((mp_digit)1 << pow) - 1;
584*f9fbec18Smcpowers     rem = DIGIT(a, 0) & mask;
585*f9fbec18Smcpowers 
586*f9fbec18Smcpowers     if(q) {
587*f9fbec18Smcpowers       mp_copy(a, q);
588*f9fbec18Smcpowers       s_mp_div_2d(q, pow);
589*f9fbec18Smcpowers     }
590*f9fbec18Smcpowers 
591*f9fbec18Smcpowers     if(r)
592*f9fbec18Smcpowers       *r = rem;
593*f9fbec18Smcpowers 
594*f9fbec18Smcpowers     return MP_OKAY;
595*f9fbec18Smcpowers   }
596*f9fbec18Smcpowers 
597*f9fbec18Smcpowers   if((res = mp_init_copy(&qp, a)) != MP_OKAY)
598*f9fbec18Smcpowers     return res;
599*f9fbec18Smcpowers 
600*f9fbec18Smcpowers   res = s_mp_div_d(&qp, d, &rem);
601*f9fbec18Smcpowers 
602*f9fbec18Smcpowers   if(s_mp_cmp_d(&qp, 0) == 0)
603*f9fbec18Smcpowers     SIGN(q) = ZPOS;
604*f9fbec18Smcpowers 
605*f9fbec18Smcpowers   if(r)
606*f9fbec18Smcpowers     *r = rem;
607*f9fbec18Smcpowers 
608*f9fbec18Smcpowers   if(q)
609*f9fbec18Smcpowers     s_mp_exch(&qp, q);
610*f9fbec18Smcpowers 
611*f9fbec18Smcpowers   mp_clear(&qp);
612*f9fbec18Smcpowers   return res;
613*f9fbec18Smcpowers 
614*f9fbec18Smcpowers } /* end mp_div_d() */
615*f9fbec18Smcpowers 
616*f9fbec18Smcpowers /* }}} */
617*f9fbec18Smcpowers 
618*f9fbec18Smcpowers /* {{{ mp_div_2(a, c) */
619*f9fbec18Smcpowers 
620*f9fbec18Smcpowers /*
621*f9fbec18Smcpowers   mp_div_2(a, c)
622*f9fbec18Smcpowers 
623*f9fbec18Smcpowers   Compute c = a / 2, disregarding the remainder.
624*f9fbec18Smcpowers  */
625*f9fbec18Smcpowers 
626*f9fbec18Smcpowers mp_err mp_div_2(const mp_int *a, mp_int *c)
627*f9fbec18Smcpowers {
628*f9fbec18Smcpowers   mp_err  res;
629*f9fbec18Smcpowers 
630*f9fbec18Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
631*f9fbec18Smcpowers 
632*f9fbec18Smcpowers   if((res = mp_copy(a, c)) != MP_OKAY)
633*f9fbec18Smcpowers     return res;
634*f9fbec18Smcpowers 
635*f9fbec18Smcpowers   s_mp_div_2(c);
636*f9fbec18Smcpowers 
637*f9fbec18Smcpowers   return MP_OKAY;
638*f9fbec18Smcpowers 
639*f9fbec18Smcpowers } /* end mp_div_2() */
640*f9fbec18Smcpowers 
641*f9fbec18Smcpowers /* }}} */
642*f9fbec18Smcpowers 
643*f9fbec18Smcpowers /* {{{ mp_expt_d(a, d, b) */
644*f9fbec18Smcpowers 
645*f9fbec18Smcpowers mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c)
646*f9fbec18Smcpowers {
647*f9fbec18Smcpowers   mp_int   s, x;
648*f9fbec18Smcpowers   mp_err   res;
649*f9fbec18Smcpowers 
650*f9fbec18Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
651*f9fbec18Smcpowers 
652*f9fbec18Smcpowers   if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
653*f9fbec18Smcpowers     return res;
654*f9fbec18Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY)
655*f9fbec18Smcpowers     goto X;
656*f9fbec18Smcpowers 
657*f9fbec18Smcpowers   DIGIT(&s, 0) = 1;
658*f9fbec18Smcpowers 
659*f9fbec18Smcpowers   while(d != 0) {
660*f9fbec18Smcpowers     if(d & 1) {
661*f9fbec18Smcpowers       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
662*f9fbec18Smcpowers 	goto CLEANUP;
663*f9fbec18Smcpowers     }
664*f9fbec18Smcpowers 
665*f9fbec18Smcpowers     d /= 2;
666*f9fbec18Smcpowers 
667*f9fbec18Smcpowers     if((res = s_mp_sqr(&x)) != MP_OKAY)
668*f9fbec18Smcpowers       goto CLEANUP;
669*f9fbec18Smcpowers   }
670*f9fbec18Smcpowers 
671*f9fbec18Smcpowers   s_mp_exch(&s, c);
672*f9fbec18Smcpowers 
673*f9fbec18Smcpowers CLEANUP:
674*f9fbec18Smcpowers   mp_clear(&x);
675*f9fbec18Smcpowers X:
676*f9fbec18Smcpowers   mp_clear(&s);
677*f9fbec18Smcpowers 
678*f9fbec18Smcpowers   return res;
679*f9fbec18Smcpowers 
680*f9fbec18Smcpowers } /* end mp_expt_d() */
681*f9fbec18Smcpowers 
682*f9fbec18Smcpowers /* }}} */
683*f9fbec18Smcpowers 
684*f9fbec18Smcpowers /* }}} */
685*f9fbec18Smcpowers 
686*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
687*f9fbec18Smcpowers /* {{{ Full arithmetic */
688*f9fbec18Smcpowers 
689*f9fbec18Smcpowers /* {{{ mp_abs(a, b) */
690*f9fbec18Smcpowers 
691*f9fbec18Smcpowers /*
692*f9fbec18Smcpowers   mp_abs(a, b)
693*f9fbec18Smcpowers 
694*f9fbec18Smcpowers   Compute b = |a|.  'a' and 'b' may be identical.
695*f9fbec18Smcpowers  */
696*f9fbec18Smcpowers 
697*f9fbec18Smcpowers mp_err mp_abs(const mp_int *a, mp_int *b)
698*f9fbec18Smcpowers {
699*f9fbec18Smcpowers   mp_err   res;
700*f9fbec18Smcpowers 
701*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
702*f9fbec18Smcpowers 
703*f9fbec18Smcpowers   if((res = mp_copy(a, b)) != MP_OKAY)
704*f9fbec18Smcpowers     return res;
705*f9fbec18Smcpowers 
706*f9fbec18Smcpowers   SIGN(b) = ZPOS;
707*f9fbec18Smcpowers 
708*f9fbec18Smcpowers   return MP_OKAY;
709*f9fbec18Smcpowers 
710*f9fbec18Smcpowers } /* end mp_abs() */
711*f9fbec18Smcpowers 
712*f9fbec18Smcpowers /* }}} */
713*f9fbec18Smcpowers 
714*f9fbec18Smcpowers /* {{{ mp_neg(a, b) */
715*f9fbec18Smcpowers 
716*f9fbec18Smcpowers /*
717*f9fbec18Smcpowers   mp_neg(a, b)
718*f9fbec18Smcpowers 
719*f9fbec18Smcpowers   Compute b = -a.  'a' and 'b' may be identical.
720*f9fbec18Smcpowers  */
721*f9fbec18Smcpowers 
722*f9fbec18Smcpowers mp_err mp_neg(const mp_int *a, mp_int *b)
723*f9fbec18Smcpowers {
724*f9fbec18Smcpowers   mp_err   res;
725*f9fbec18Smcpowers 
726*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
727*f9fbec18Smcpowers 
728*f9fbec18Smcpowers   if((res = mp_copy(a, b)) != MP_OKAY)
729*f9fbec18Smcpowers     return res;
730*f9fbec18Smcpowers 
731*f9fbec18Smcpowers   if(s_mp_cmp_d(b, 0) == MP_EQ)
732*f9fbec18Smcpowers     SIGN(b) = ZPOS;
733*f9fbec18Smcpowers   else
734*f9fbec18Smcpowers     SIGN(b) = (SIGN(b) == NEG) ? ZPOS : NEG;
735*f9fbec18Smcpowers 
736*f9fbec18Smcpowers   return MP_OKAY;
737*f9fbec18Smcpowers 
738*f9fbec18Smcpowers } /* end mp_neg() */
739*f9fbec18Smcpowers 
740*f9fbec18Smcpowers /* }}} */
741*f9fbec18Smcpowers 
742*f9fbec18Smcpowers /* {{{ mp_add(a, b, c) */
743*f9fbec18Smcpowers 
744*f9fbec18Smcpowers /*
745*f9fbec18Smcpowers   mp_add(a, b, c)
746*f9fbec18Smcpowers 
747*f9fbec18Smcpowers   Compute c = a + b.  All parameters may be identical.
748*f9fbec18Smcpowers  */
749*f9fbec18Smcpowers 
750*f9fbec18Smcpowers mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c)
751*f9fbec18Smcpowers {
752*f9fbec18Smcpowers   mp_err  res;
753*f9fbec18Smcpowers 
754*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
755*f9fbec18Smcpowers 
756*f9fbec18Smcpowers   if(SIGN(a) == SIGN(b)) { /* same sign:  add values, keep sign */
757*f9fbec18Smcpowers     MP_CHECKOK( s_mp_add_3arg(a, b, c) );
758*f9fbec18Smcpowers   } else if(s_mp_cmp(a, b) >= 0) {  /* different sign: |a| >= |b|   */
759*f9fbec18Smcpowers     MP_CHECKOK( s_mp_sub_3arg(a, b, c) );
760*f9fbec18Smcpowers   } else {                          /* different sign: |a|  < |b|   */
761*f9fbec18Smcpowers     MP_CHECKOK( s_mp_sub_3arg(b, a, c) );
762*f9fbec18Smcpowers   }
763*f9fbec18Smcpowers 
764*f9fbec18Smcpowers   if (s_mp_cmp_d(c, 0) == MP_EQ)
765*f9fbec18Smcpowers     SIGN(c) = ZPOS;
766*f9fbec18Smcpowers 
767*f9fbec18Smcpowers CLEANUP:
768*f9fbec18Smcpowers   return res;
769*f9fbec18Smcpowers 
770*f9fbec18Smcpowers } /* end mp_add() */
771*f9fbec18Smcpowers 
772*f9fbec18Smcpowers /* }}} */
773*f9fbec18Smcpowers 
774*f9fbec18Smcpowers /* {{{ mp_sub(a, b, c) */
775*f9fbec18Smcpowers 
776*f9fbec18Smcpowers /*
777*f9fbec18Smcpowers   mp_sub(a, b, c)
778*f9fbec18Smcpowers 
779*f9fbec18Smcpowers   Compute c = a - b.  All parameters may be identical.
780*f9fbec18Smcpowers  */
781*f9fbec18Smcpowers 
782*f9fbec18Smcpowers mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
783*f9fbec18Smcpowers {
784*f9fbec18Smcpowers   mp_err  res;
785*f9fbec18Smcpowers   int     magDiff;
786*f9fbec18Smcpowers 
787*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
788*f9fbec18Smcpowers 
789*f9fbec18Smcpowers   if (a == b) {
790*f9fbec18Smcpowers     mp_zero(c);
791*f9fbec18Smcpowers     return MP_OKAY;
792*f9fbec18Smcpowers   }
793*f9fbec18Smcpowers 
794*f9fbec18Smcpowers   if (MP_SIGN(a) != MP_SIGN(b)) {
795*f9fbec18Smcpowers     MP_CHECKOK( s_mp_add_3arg(a, b, c) );
796*f9fbec18Smcpowers   } else if (!(magDiff = s_mp_cmp(a, b))) {
797*f9fbec18Smcpowers     mp_zero(c);
798*f9fbec18Smcpowers     res = MP_OKAY;
799*f9fbec18Smcpowers   } else if (magDiff > 0) {
800*f9fbec18Smcpowers     MP_CHECKOK( s_mp_sub_3arg(a, b, c) );
801*f9fbec18Smcpowers   } else {
802*f9fbec18Smcpowers     MP_CHECKOK( s_mp_sub_3arg(b, a, c) );
803*f9fbec18Smcpowers     MP_SIGN(c) = !MP_SIGN(a);
804*f9fbec18Smcpowers   }
805*f9fbec18Smcpowers 
806*f9fbec18Smcpowers   if (s_mp_cmp_d(c, 0) == MP_EQ)
807*f9fbec18Smcpowers     MP_SIGN(c) = MP_ZPOS;
808*f9fbec18Smcpowers 
809*f9fbec18Smcpowers CLEANUP:
810*f9fbec18Smcpowers   return res;
811*f9fbec18Smcpowers 
812*f9fbec18Smcpowers } /* end mp_sub() */
813*f9fbec18Smcpowers 
814*f9fbec18Smcpowers /* }}} */
815*f9fbec18Smcpowers 
816*f9fbec18Smcpowers /* {{{ mp_mul(a, b, c) */
817*f9fbec18Smcpowers 
818*f9fbec18Smcpowers /*
819*f9fbec18Smcpowers   mp_mul(a, b, c)
820*f9fbec18Smcpowers 
821*f9fbec18Smcpowers   Compute c = a * b.  All parameters may be identical.
822*f9fbec18Smcpowers  */
823*f9fbec18Smcpowers mp_err   mp_mul(const mp_int *a, const mp_int *b, mp_int * c)
824*f9fbec18Smcpowers {
825*f9fbec18Smcpowers   mp_digit *pb;
826*f9fbec18Smcpowers   mp_int   tmp;
827*f9fbec18Smcpowers   mp_err   res;
828*f9fbec18Smcpowers   mp_size  ib;
829*f9fbec18Smcpowers   mp_size  useda, usedb;
830*f9fbec18Smcpowers 
831*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
832*f9fbec18Smcpowers 
833*f9fbec18Smcpowers   if (a == c) {
834*f9fbec18Smcpowers     if ((res = mp_init_copy(&tmp, a)) != MP_OKAY)
835*f9fbec18Smcpowers       return res;
836*f9fbec18Smcpowers     if (a == b)
837*f9fbec18Smcpowers       b = &tmp;
838*f9fbec18Smcpowers     a = &tmp;
839*f9fbec18Smcpowers   } else if (b == c) {
840*f9fbec18Smcpowers     if ((res = mp_init_copy(&tmp, b)) != MP_OKAY)
841*f9fbec18Smcpowers       return res;
842*f9fbec18Smcpowers     b = &tmp;
843*f9fbec18Smcpowers   } else {
844*f9fbec18Smcpowers     MP_DIGITS(&tmp) = 0;
845*f9fbec18Smcpowers   }
846*f9fbec18Smcpowers 
847*f9fbec18Smcpowers   if (MP_USED(a) < MP_USED(b)) {
848*f9fbec18Smcpowers     const mp_int *xch = b;	/* switch a and b, to do fewer outer loops */
849*f9fbec18Smcpowers     b = a;
850*f9fbec18Smcpowers     a = xch;
851*f9fbec18Smcpowers   }
852*f9fbec18Smcpowers 
853*f9fbec18Smcpowers   MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
854*f9fbec18Smcpowers   if((res = s_mp_pad(c, USED(a) + USED(b))) != MP_OKAY)
855*f9fbec18Smcpowers     goto CLEANUP;
856*f9fbec18Smcpowers 
857*f9fbec18Smcpowers #ifdef NSS_USE_COMBA
858*f9fbec18Smcpowers   if ((MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) {
859*f9fbec18Smcpowers       if (MP_USED(a) == 4) {
860*f9fbec18Smcpowers           s_mp_mul_comba_4(a, b, c);
861*f9fbec18Smcpowers           goto CLEANUP;
862*f9fbec18Smcpowers       }
863*f9fbec18Smcpowers       if (MP_USED(a) == 8) {
864*f9fbec18Smcpowers           s_mp_mul_comba_8(a, b, c);
865*f9fbec18Smcpowers           goto CLEANUP;
866*f9fbec18Smcpowers       }
867*f9fbec18Smcpowers       if (MP_USED(a) == 16) {
868*f9fbec18Smcpowers           s_mp_mul_comba_16(a, b, c);
869*f9fbec18Smcpowers           goto CLEANUP;
870*f9fbec18Smcpowers       }
871*f9fbec18Smcpowers       if (MP_USED(a) == 32) {
872*f9fbec18Smcpowers           s_mp_mul_comba_32(a, b, c);
873*f9fbec18Smcpowers           goto CLEANUP;
874*f9fbec18Smcpowers       }
875*f9fbec18Smcpowers   }
876*f9fbec18Smcpowers #endif
877*f9fbec18Smcpowers 
878*f9fbec18Smcpowers   pb = MP_DIGITS(b);
879*f9fbec18Smcpowers   s_mpv_mul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
880*f9fbec18Smcpowers 
881*f9fbec18Smcpowers   /* Outer loop:  Digits of b */
882*f9fbec18Smcpowers   useda = MP_USED(a);
883*f9fbec18Smcpowers   usedb = MP_USED(b);
884*f9fbec18Smcpowers   for (ib = 1; ib < usedb; ib++) {
885*f9fbec18Smcpowers     mp_digit b_i    = *pb++;
886*f9fbec18Smcpowers 
887*f9fbec18Smcpowers     /* Inner product:  Digits of a */
888*f9fbec18Smcpowers     if (b_i)
889*f9fbec18Smcpowers       s_mpv_mul_d_add(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
890*f9fbec18Smcpowers     else
891*f9fbec18Smcpowers       MP_DIGIT(c, ib + useda) = b_i;
892*f9fbec18Smcpowers   }
893*f9fbec18Smcpowers 
894*f9fbec18Smcpowers   s_mp_clamp(c);
895*f9fbec18Smcpowers 
896*f9fbec18Smcpowers   if(SIGN(a) == SIGN(b) || s_mp_cmp_d(c, 0) == MP_EQ)
897*f9fbec18Smcpowers     SIGN(c) = ZPOS;
898*f9fbec18Smcpowers   else
899*f9fbec18Smcpowers     SIGN(c) = NEG;
900*f9fbec18Smcpowers 
901*f9fbec18Smcpowers CLEANUP:
902*f9fbec18Smcpowers   mp_clear(&tmp);
903*f9fbec18Smcpowers   return res;
904*f9fbec18Smcpowers } /* end mp_mul() */
905*f9fbec18Smcpowers 
906*f9fbec18Smcpowers /* }}} */
907*f9fbec18Smcpowers 
908*f9fbec18Smcpowers /* {{{ mp_sqr(a, sqr) */
909*f9fbec18Smcpowers 
910*f9fbec18Smcpowers #if MP_SQUARE
911*f9fbec18Smcpowers /*
912*f9fbec18Smcpowers   Computes the square of a.  This can be done more
913*f9fbec18Smcpowers   efficiently than a general multiplication, because many of the
914*f9fbec18Smcpowers   computation steps are redundant when squaring.  The inner product
915*f9fbec18Smcpowers   step is a bit more complicated, but we save a fair number of
916*f9fbec18Smcpowers   iterations of the multiplication loop.
917*f9fbec18Smcpowers  */
918*f9fbec18Smcpowers 
919*f9fbec18Smcpowers /* sqr = a^2;   Caller provides both a and tmp; */
920*f9fbec18Smcpowers mp_err   mp_sqr(const mp_int *a, mp_int *sqr)
921*f9fbec18Smcpowers {
922*f9fbec18Smcpowers   mp_digit *pa;
923*f9fbec18Smcpowers   mp_digit d;
924*f9fbec18Smcpowers   mp_err   res;
925*f9fbec18Smcpowers   mp_size  ix;
926*f9fbec18Smcpowers   mp_int   tmp;
927*f9fbec18Smcpowers   int      count;
928*f9fbec18Smcpowers 
929*f9fbec18Smcpowers   ARGCHK(a != NULL && sqr != NULL, MP_BADARG);
930*f9fbec18Smcpowers 
931*f9fbec18Smcpowers   if (a == sqr) {
932*f9fbec18Smcpowers     if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
933*f9fbec18Smcpowers       return res;
934*f9fbec18Smcpowers     a = &tmp;
935*f9fbec18Smcpowers   } else {
936*f9fbec18Smcpowers     DIGITS(&tmp) = 0;
937*f9fbec18Smcpowers     res = MP_OKAY;
938*f9fbec18Smcpowers   }
939*f9fbec18Smcpowers 
940*f9fbec18Smcpowers   ix = 2 * MP_USED(a);
941*f9fbec18Smcpowers   if (ix > MP_ALLOC(sqr)) {
942*f9fbec18Smcpowers     MP_USED(sqr) = 1;
943*f9fbec18Smcpowers     MP_CHECKOK( s_mp_grow(sqr, ix) );
944*f9fbec18Smcpowers   }
945*f9fbec18Smcpowers   MP_USED(sqr) = ix;
946*f9fbec18Smcpowers   MP_DIGIT(sqr, 0) = 0;
947*f9fbec18Smcpowers 
948*f9fbec18Smcpowers #ifdef NSS_USE_COMBA
949*f9fbec18Smcpowers   if (IS_POWER_OF_2(MP_USED(a))) {
950*f9fbec18Smcpowers       if (MP_USED(a) == 4) {
951*f9fbec18Smcpowers           s_mp_sqr_comba_4(a, sqr);
952*f9fbec18Smcpowers           goto CLEANUP;
953*f9fbec18Smcpowers       }
954*f9fbec18Smcpowers       if (MP_USED(a) == 8) {
955*f9fbec18Smcpowers           s_mp_sqr_comba_8(a, sqr);
956*f9fbec18Smcpowers           goto CLEANUP;
957*f9fbec18Smcpowers       }
958*f9fbec18Smcpowers       if (MP_USED(a) == 16) {
959*f9fbec18Smcpowers           s_mp_sqr_comba_16(a, sqr);
960*f9fbec18Smcpowers           goto CLEANUP;
961*f9fbec18Smcpowers       }
962*f9fbec18Smcpowers       if (MP_USED(a) == 32) {
963*f9fbec18Smcpowers           s_mp_sqr_comba_32(a, sqr);
964*f9fbec18Smcpowers           goto CLEANUP;
965*f9fbec18Smcpowers       }
966*f9fbec18Smcpowers   }
967*f9fbec18Smcpowers #endif
968*f9fbec18Smcpowers 
969*f9fbec18Smcpowers   pa = MP_DIGITS(a);
970*f9fbec18Smcpowers   count = MP_USED(a) - 1;
971*f9fbec18Smcpowers   if (count > 0) {
972*f9fbec18Smcpowers     d = *pa++;
973*f9fbec18Smcpowers     s_mpv_mul_d(pa, count, d, MP_DIGITS(sqr) + 1);
974*f9fbec18Smcpowers     for (ix = 3; --count > 0; ix += 2) {
975*f9fbec18Smcpowers       d = *pa++;
976*f9fbec18Smcpowers       s_mpv_mul_d_add(pa, count, d, MP_DIGITS(sqr) + ix);
977*f9fbec18Smcpowers     } /* for(ix ...) */
978*f9fbec18Smcpowers     MP_DIGIT(sqr, MP_USED(sqr)-1) = 0; /* above loop stopped short of this. */
979*f9fbec18Smcpowers 
980*f9fbec18Smcpowers     /* now sqr *= 2 */
981*f9fbec18Smcpowers     s_mp_mul_2(sqr);
982*f9fbec18Smcpowers   } else {
983*f9fbec18Smcpowers     MP_DIGIT(sqr, 1) = 0;
984*f9fbec18Smcpowers   }
985*f9fbec18Smcpowers 
986*f9fbec18Smcpowers   /* now add the squares of the digits of a to sqr. */
987*f9fbec18Smcpowers   s_mpv_sqr_add_prop(MP_DIGITS(a), MP_USED(a), MP_DIGITS(sqr));
988*f9fbec18Smcpowers 
989*f9fbec18Smcpowers   SIGN(sqr) = ZPOS;
990*f9fbec18Smcpowers   s_mp_clamp(sqr);
991*f9fbec18Smcpowers 
992*f9fbec18Smcpowers CLEANUP:
993*f9fbec18Smcpowers   mp_clear(&tmp);
994*f9fbec18Smcpowers   return res;
995*f9fbec18Smcpowers 
996*f9fbec18Smcpowers } /* end mp_sqr() */
997*f9fbec18Smcpowers #endif
998*f9fbec18Smcpowers 
999*f9fbec18Smcpowers /* }}} */
1000*f9fbec18Smcpowers 
1001*f9fbec18Smcpowers /* {{{ mp_div(a, b, q, r) */
1002*f9fbec18Smcpowers 
1003*f9fbec18Smcpowers /*
1004*f9fbec18Smcpowers   mp_div(a, b, q, r)
1005*f9fbec18Smcpowers 
1006*f9fbec18Smcpowers   Compute q = a / b and r = a mod b.  Input parameters may be re-used
1007*f9fbec18Smcpowers   as output parameters.  If q or r is NULL, that portion of the
1008*f9fbec18Smcpowers   computation will be discarded (although it will still be computed)
1009*f9fbec18Smcpowers  */
1010*f9fbec18Smcpowers mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r)
1011*f9fbec18Smcpowers {
1012*f9fbec18Smcpowers   mp_err   res;
1013*f9fbec18Smcpowers   mp_int   *pQ, *pR;
1014*f9fbec18Smcpowers   mp_int   qtmp, rtmp, btmp;
1015*f9fbec18Smcpowers   int      cmp;
1016*f9fbec18Smcpowers   mp_sign  signA;
1017*f9fbec18Smcpowers   mp_sign  signB;
1018*f9fbec18Smcpowers 
1019*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
1020*f9fbec18Smcpowers 
1021*f9fbec18Smcpowers   signA = MP_SIGN(a);
1022*f9fbec18Smcpowers   signB = MP_SIGN(b);
1023*f9fbec18Smcpowers 
1024*f9fbec18Smcpowers   if(mp_cmp_z(b) == MP_EQ)
1025*f9fbec18Smcpowers     return MP_RANGE;
1026*f9fbec18Smcpowers 
1027*f9fbec18Smcpowers   DIGITS(&qtmp) = 0;
1028*f9fbec18Smcpowers   DIGITS(&rtmp) = 0;
1029*f9fbec18Smcpowers   DIGITS(&btmp) = 0;
1030*f9fbec18Smcpowers 
1031*f9fbec18Smcpowers   /* Set up some temporaries... */
1032*f9fbec18Smcpowers   if (!r || r == a || r == b) {
1033*f9fbec18Smcpowers     MP_CHECKOK( mp_init_copy(&rtmp, a) );
1034*f9fbec18Smcpowers     pR = &rtmp;
1035*f9fbec18Smcpowers   } else {
1036*f9fbec18Smcpowers     MP_CHECKOK( mp_copy(a, r) );
1037*f9fbec18Smcpowers     pR = r;
1038*f9fbec18Smcpowers   }
1039*f9fbec18Smcpowers 
1040*f9fbec18Smcpowers   if (!q || q == a || q == b) {
1041*f9fbec18Smcpowers     MP_CHECKOK( mp_init_size(&qtmp, MP_USED(a), FLAG(a)) );
1042*f9fbec18Smcpowers     pQ = &qtmp;
1043*f9fbec18Smcpowers   } else {
1044*f9fbec18Smcpowers     MP_CHECKOK( s_mp_pad(q, MP_USED(a)) );
1045*f9fbec18Smcpowers     pQ = q;
1046*f9fbec18Smcpowers     mp_zero(pQ);
1047*f9fbec18Smcpowers   }
1048*f9fbec18Smcpowers 
1049*f9fbec18Smcpowers   /*
1050*f9fbec18Smcpowers     If |a| <= |b|, we can compute the solution without division;
1051*f9fbec18Smcpowers     otherwise, we actually do the work required.
1052*f9fbec18Smcpowers    */
1053*f9fbec18Smcpowers   if ((cmp = s_mp_cmp(a, b)) <= 0) {
1054*f9fbec18Smcpowers     if (cmp) {
1055*f9fbec18Smcpowers       /* r was set to a above. */
1056*f9fbec18Smcpowers       mp_zero(pQ);
1057*f9fbec18Smcpowers     } else {
1058*f9fbec18Smcpowers       mp_set(pQ, 1);
1059*f9fbec18Smcpowers       mp_zero(pR);
1060*f9fbec18Smcpowers     }
1061*f9fbec18Smcpowers   } else {
1062*f9fbec18Smcpowers     MP_CHECKOK( mp_init_copy(&btmp, b) );
1063*f9fbec18Smcpowers     MP_CHECKOK( s_mp_div(pR, &btmp, pQ) );
1064*f9fbec18Smcpowers   }
1065*f9fbec18Smcpowers 
1066*f9fbec18Smcpowers   /* Compute the signs for the output  */
1067*f9fbec18Smcpowers   MP_SIGN(pR) = signA;   /* Sr = Sa              */
1068*f9fbec18Smcpowers   /* Sq = ZPOS if Sa == Sb */ /* Sq = NEG if Sa != Sb */
1069*f9fbec18Smcpowers   MP_SIGN(pQ) = (signA == signB) ? ZPOS : NEG;
1070*f9fbec18Smcpowers 
1071*f9fbec18Smcpowers   if(s_mp_cmp_d(pQ, 0) == MP_EQ)
1072*f9fbec18Smcpowers     SIGN(pQ) = ZPOS;
1073*f9fbec18Smcpowers   if(s_mp_cmp_d(pR, 0) == MP_EQ)
1074*f9fbec18Smcpowers     SIGN(pR) = ZPOS;
1075*f9fbec18Smcpowers 
1076*f9fbec18Smcpowers   /* Copy output, if it is needed      */
1077*f9fbec18Smcpowers   if(q && q != pQ)
1078*f9fbec18Smcpowers     s_mp_exch(pQ, q);
1079*f9fbec18Smcpowers 
1080*f9fbec18Smcpowers   if(r && r != pR)
1081*f9fbec18Smcpowers     s_mp_exch(pR, r);
1082*f9fbec18Smcpowers 
1083*f9fbec18Smcpowers CLEANUP:
1084*f9fbec18Smcpowers   mp_clear(&btmp);
1085*f9fbec18Smcpowers   mp_clear(&rtmp);
1086*f9fbec18Smcpowers   mp_clear(&qtmp);
1087*f9fbec18Smcpowers 
1088*f9fbec18Smcpowers   return res;
1089*f9fbec18Smcpowers 
1090*f9fbec18Smcpowers } /* end mp_div() */
1091*f9fbec18Smcpowers 
1092*f9fbec18Smcpowers /* }}} */
1093*f9fbec18Smcpowers 
1094*f9fbec18Smcpowers /* {{{ mp_div_2d(a, d, q, r) */
1095*f9fbec18Smcpowers 
1096*f9fbec18Smcpowers mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r)
1097*f9fbec18Smcpowers {
1098*f9fbec18Smcpowers   mp_err  res;
1099*f9fbec18Smcpowers 
1100*f9fbec18Smcpowers   ARGCHK(a != NULL, MP_BADARG);
1101*f9fbec18Smcpowers 
1102*f9fbec18Smcpowers   if(q) {
1103*f9fbec18Smcpowers     if((res = mp_copy(a, q)) != MP_OKAY)
1104*f9fbec18Smcpowers       return res;
1105*f9fbec18Smcpowers   }
1106*f9fbec18Smcpowers   if(r) {
1107*f9fbec18Smcpowers     if((res = mp_copy(a, r)) != MP_OKAY)
1108*f9fbec18Smcpowers       return res;
1109*f9fbec18Smcpowers   }
1110*f9fbec18Smcpowers   if(q) {
1111*f9fbec18Smcpowers     s_mp_div_2d(q, d);
1112*f9fbec18Smcpowers   }
1113*f9fbec18Smcpowers   if(r) {
1114*f9fbec18Smcpowers     s_mp_mod_2d(r, d);
1115*f9fbec18Smcpowers   }
1116*f9fbec18Smcpowers 
1117*f9fbec18Smcpowers   return MP_OKAY;
1118*f9fbec18Smcpowers 
1119*f9fbec18Smcpowers } /* end mp_div_2d() */
1120*f9fbec18Smcpowers 
1121*f9fbec18Smcpowers /* }}} */
1122*f9fbec18Smcpowers 
1123*f9fbec18Smcpowers /* {{{ mp_expt(a, b, c) */
1124*f9fbec18Smcpowers 
1125*f9fbec18Smcpowers /*
1126*f9fbec18Smcpowers   mp_expt(a, b, c)
1127*f9fbec18Smcpowers 
1128*f9fbec18Smcpowers   Compute c = a ** b, that is, raise a to the b power.  Uses a
1129*f9fbec18Smcpowers   standard iterative square-and-multiply technique.
1130*f9fbec18Smcpowers  */
1131*f9fbec18Smcpowers 
1132*f9fbec18Smcpowers mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c)
1133*f9fbec18Smcpowers {
1134*f9fbec18Smcpowers   mp_int   s, x;
1135*f9fbec18Smcpowers   mp_err   res;
1136*f9fbec18Smcpowers   mp_digit d;
1137*f9fbec18Smcpowers   int      dig, bit;
1138*f9fbec18Smcpowers 
1139*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
1140*f9fbec18Smcpowers 
1141*f9fbec18Smcpowers   if(mp_cmp_z(b) < 0)
1142*f9fbec18Smcpowers     return MP_RANGE;
1143*f9fbec18Smcpowers 
1144*f9fbec18Smcpowers   if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
1145*f9fbec18Smcpowers     return res;
1146*f9fbec18Smcpowers 
1147*f9fbec18Smcpowers   mp_set(&s, 1);
1148*f9fbec18Smcpowers 
1149*f9fbec18Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY)
1150*f9fbec18Smcpowers     goto X;
1151*f9fbec18Smcpowers 
1152*f9fbec18Smcpowers   /* Loop over low-order digits in ascending order */
1153*f9fbec18Smcpowers   for(dig = 0; dig < (USED(b) - 1); dig++) {
1154*f9fbec18Smcpowers     d = DIGIT(b, dig);
1155*f9fbec18Smcpowers 
1156*f9fbec18Smcpowers     /* Loop over bits of each non-maximal digit */
1157*f9fbec18Smcpowers     for(bit = 0; bit < DIGIT_BIT; bit++) {
1158*f9fbec18Smcpowers       if(d & 1) {
1159*f9fbec18Smcpowers 	if((res = s_mp_mul(&s, &x)) != MP_OKAY)
1160*f9fbec18Smcpowers 	  goto CLEANUP;
1161*f9fbec18Smcpowers       }
1162*f9fbec18Smcpowers 
1163*f9fbec18Smcpowers       d >>= 1;
1164*f9fbec18Smcpowers 
1165*f9fbec18Smcpowers       if((res = s_mp_sqr(&x)) != MP_OKAY)
1166*f9fbec18Smcpowers 	goto CLEANUP;
1167*f9fbec18Smcpowers     }
1168*f9fbec18Smcpowers   }
1169*f9fbec18Smcpowers 
1170*f9fbec18Smcpowers   /* Consider now the last digit... */
1171*f9fbec18Smcpowers   d = DIGIT(b, dig);
1172*f9fbec18Smcpowers 
1173*f9fbec18Smcpowers   while(d) {
1174*f9fbec18Smcpowers     if(d & 1) {
1175*f9fbec18Smcpowers       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
1176*f9fbec18Smcpowers 	goto CLEANUP;
1177*f9fbec18Smcpowers     }
1178*f9fbec18Smcpowers 
1179*f9fbec18Smcpowers     d >>= 1;
1180*f9fbec18Smcpowers 
1181*f9fbec18Smcpowers     if((res = s_mp_sqr(&x)) != MP_OKAY)
1182*f9fbec18Smcpowers       goto CLEANUP;
1183*f9fbec18Smcpowers   }
1184*f9fbec18Smcpowers 
1185*f9fbec18Smcpowers   if(mp_iseven(b))
1186*f9fbec18Smcpowers     SIGN(&s) = SIGN(a);
1187*f9fbec18Smcpowers 
1188*f9fbec18Smcpowers   res = mp_copy(&s, c);
1189*f9fbec18Smcpowers 
1190*f9fbec18Smcpowers CLEANUP:
1191*f9fbec18Smcpowers   mp_clear(&x);
1192*f9fbec18Smcpowers X:
1193*f9fbec18Smcpowers   mp_clear(&s);
1194*f9fbec18Smcpowers 
1195*f9fbec18Smcpowers   return res;
1196*f9fbec18Smcpowers 
1197*f9fbec18Smcpowers } /* end mp_expt() */
1198*f9fbec18Smcpowers 
1199*f9fbec18Smcpowers /* }}} */
1200*f9fbec18Smcpowers 
1201*f9fbec18Smcpowers /* {{{ mp_2expt(a, k) */
1202*f9fbec18Smcpowers 
1203*f9fbec18Smcpowers /* Compute a = 2^k */
1204*f9fbec18Smcpowers 
1205*f9fbec18Smcpowers mp_err mp_2expt(mp_int *a, mp_digit k)
1206*f9fbec18Smcpowers {
1207*f9fbec18Smcpowers   ARGCHK(a != NULL, MP_BADARG);
1208*f9fbec18Smcpowers 
1209*f9fbec18Smcpowers   return s_mp_2expt(a, k);
1210*f9fbec18Smcpowers 
1211*f9fbec18Smcpowers } /* end mp_2expt() */
1212*f9fbec18Smcpowers 
1213*f9fbec18Smcpowers /* }}} */
1214*f9fbec18Smcpowers 
1215*f9fbec18Smcpowers /* {{{ mp_mod(a, m, c) */
1216*f9fbec18Smcpowers 
1217*f9fbec18Smcpowers /*
1218*f9fbec18Smcpowers   mp_mod(a, m, c)
1219*f9fbec18Smcpowers 
1220*f9fbec18Smcpowers   Compute c = a (mod m).  Result will always be 0 <= c < m.
1221*f9fbec18Smcpowers  */
1222*f9fbec18Smcpowers 
1223*f9fbec18Smcpowers mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c)
1224*f9fbec18Smcpowers {
1225*f9fbec18Smcpowers   mp_err  res;
1226*f9fbec18Smcpowers   int     mag;
1227*f9fbec18Smcpowers 
1228*f9fbec18Smcpowers   ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
1229*f9fbec18Smcpowers 
1230*f9fbec18Smcpowers   if(SIGN(m) == NEG)
1231*f9fbec18Smcpowers     return MP_RANGE;
1232*f9fbec18Smcpowers 
1233*f9fbec18Smcpowers   /*
1234*f9fbec18Smcpowers      If |a| > m, we need to divide to get the remainder and take the
1235*f9fbec18Smcpowers      absolute value.
1236*f9fbec18Smcpowers 
1237*f9fbec18Smcpowers      If |a| < m, we don't need to do any division, just copy and adjust
1238*f9fbec18Smcpowers      the sign (if a is negative).
1239*f9fbec18Smcpowers 
1240*f9fbec18Smcpowers      If |a| == m, we can simply set the result to zero.
1241*f9fbec18Smcpowers 
1242*f9fbec18Smcpowers      This order is intended to minimize the average path length of the
1243*f9fbec18Smcpowers      comparison chain on common workloads -- the most frequent cases are
1244*f9fbec18Smcpowers      that |a| != m, so we do those first.
1245*f9fbec18Smcpowers    */
1246*f9fbec18Smcpowers   if((mag = s_mp_cmp(a, m)) > 0) {
1247*f9fbec18Smcpowers     if((res = mp_div(a, m, NULL, c)) != MP_OKAY)
1248*f9fbec18Smcpowers       return res;
1249*f9fbec18Smcpowers 
1250*f9fbec18Smcpowers     if(SIGN(c) == NEG) {
1251*f9fbec18Smcpowers       if((res = mp_add(c, m, c)) != MP_OKAY)
1252*f9fbec18Smcpowers 	return res;
1253*f9fbec18Smcpowers     }
1254*f9fbec18Smcpowers 
1255*f9fbec18Smcpowers   } else if(mag < 0) {
1256*f9fbec18Smcpowers     if((res = mp_copy(a, c)) != MP_OKAY)
1257*f9fbec18Smcpowers       return res;
1258*f9fbec18Smcpowers 
1259*f9fbec18Smcpowers     if(mp_cmp_z(a) < 0) {
1260*f9fbec18Smcpowers       if((res = mp_add(c, m, c)) != MP_OKAY)
1261*f9fbec18Smcpowers 	return res;
1262*f9fbec18Smcpowers 
1263*f9fbec18Smcpowers     }
1264*f9fbec18Smcpowers 
1265*f9fbec18Smcpowers   } else {
1266*f9fbec18Smcpowers     mp_zero(c);
1267*f9fbec18Smcpowers 
1268*f9fbec18Smcpowers   }
1269*f9fbec18Smcpowers 
1270*f9fbec18Smcpowers   return MP_OKAY;
1271*f9fbec18Smcpowers 
1272*f9fbec18Smcpowers } /* end mp_mod() */
1273*f9fbec18Smcpowers 
1274*f9fbec18Smcpowers /* }}} */
1275*f9fbec18Smcpowers 
1276*f9fbec18Smcpowers /* {{{ mp_mod_d(a, d, c) */
1277*f9fbec18Smcpowers 
1278*f9fbec18Smcpowers /*
1279*f9fbec18Smcpowers   mp_mod_d(a, d, c)
1280*f9fbec18Smcpowers 
1281*f9fbec18Smcpowers   Compute c = a (mod d).  Result will always be 0 <= c < d
1282*f9fbec18Smcpowers  */
1283*f9fbec18Smcpowers mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c)
1284*f9fbec18Smcpowers {
1285*f9fbec18Smcpowers   mp_err   res;
1286*f9fbec18Smcpowers   mp_digit rem;
1287*f9fbec18Smcpowers 
1288*f9fbec18Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
1289*f9fbec18Smcpowers 
1290*f9fbec18Smcpowers   if(s_mp_cmp_d(a, d) > 0) {
1291*f9fbec18Smcpowers     if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)
1292*f9fbec18Smcpowers       return res;
1293*f9fbec18Smcpowers 
1294*f9fbec18Smcpowers   } else {
1295*f9fbec18Smcpowers     if(SIGN(a) == NEG)
1296*f9fbec18Smcpowers       rem = d - DIGIT(a, 0);
1297*f9fbec18Smcpowers     else
1298*f9fbec18Smcpowers       rem = DIGIT(a, 0);
1299*f9fbec18Smcpowers   }
1300*f9fbec18Smcpowers 
1301*f9fbec18Smcpowers   if(c)
1302*f9fbec18Smcpowers     *c = rem;
1303*f9fbec18Smcpowers 
1304*f9fbec18Smcpowers   return MP_OKAY;
1305*f9fbec18Smcpowers 
1306*f9fbec18Smcpowers } /* end mp_mod_d() */
1307*f9fbec18Smcpowers 
1308*f9fbec18Smcpowers /* }}} */
1309*f9fbec18Smcpowers 
1310*f9fbec18Smcpowers /* {{{ mp_sqrt(a, b) */
1311*f9fbec18Smcpowers 
1312*f9fbec18Smcpowers /*
1313*f9fbec18Smcpowers   mp_sqrt(a, b)
1314*f9fbec18Smcpowers 
1315*f9fbec18Smcpowers   Compute the integer square root of a, and store the result in b.
1316*f9fbec18Smcpowers   Uses an integer-arithmetic version of Newton's iterative linear
1317*f9fbec18Smcpowers   approximation technique to determine this value; the result has the
1318*f9fbec18Smcpowers   following two properties:
1319*f9fbec18Smcpowers 
1320*f9fbec18Smcpowers      b^2 <= a
1321*f9fbec18Smcpowers      (b+1)^2 >= a
1322*f9fbec18Smcpowers 
1323*f9fbec18Smcpowers   It is a range error to pass a negative value.
1324*f9fbec18Smcpowers  */
1325*f9fbec18Smcpowers mp_err mp_sqrt(const mp_int *a, mp_int *b)
1326*f9fbec18Smcpowers {
1327*f9fbec18Smcpowers   mp_int   x, t;
1328*f9fbec18Smcpowers   mp_err   res;
1329*f9fbec18Smcpowers   mp_size  used;
1330*f9fbec18Smcpowers 
1331*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
1332*f9fbec18Smcpowers 
1333*f9fbec18Smcpowers   /* Cannot take square root of a negative value */
1334*f9fbec18Smcpowers   if(SIGN(a) == NEG)
1335*f9fbec18Smcpowers     return MP_RANGE;
1336*f9fbec18Smcpowers 
1337*f9fbec18Smcpowers   /* Special cases for zero and one, trivial     */
1338*f9fbec18Smcpowers   if(mp_cmp_d(a, 1) <= 0)
1339*f9fbec18Smcpowers     return mp_copy(a, b);
1340*f9fbec18Smcpowers 
1341*f9fbec18Smcpowers   /* Initialize the temporaries we'll use below  */
1342*f9fbec18Smcpowers   if((res = mp_init_size(&t, USED(a), FLAG(a))) != MP_OKAY)
1343*f9fbec18Smcpowers     return res;
1344*f9fbec18Smcpowers 
1345*f9fbec18Smcpowers   /* Compute an initial guess for the iteration as a itself */
1346*f9fbec18Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY)
1347*f9fbec18Smcpowers     goto X;
1348*f9fbec18Smcpowers 
1349*f9fbec18Smcpowers   used = MP_USED(&x);
1350*f9fbec18Smcpowers   if (used > 1) {
1351*f9fbec18Smcpowers     s_mp_rshd(&x, used / 2);
1352*f9fbec18Smcpowers   }
1353*f9fbec18Smcpowers 
1354*f9fbec18Smcpowers   for(;;) {
1355*f9fbec18Smcpowers     /* t = (x * x) - a */
1356*f9fbec18Smcpowers     mp_copy(&x, &t);      /* can't fail, t is big enough for original x */
1357*f9fbec18Smcpowers     if((res = mp_sqr(&t, &t)) != MP_OKAY ||
1358*f9fbec18Smcpowers        (res = mp_sub(&t, a, &t)) != MP_OKAY)
1359*f9fbec18Smcpowers       goto CLEANUP;
1360*f9fbec18Smcpowers 
1361*f9fbec18Smcpowers     /* t = t / 2x       */
1362*f9fbec18Smcpowers     s_mp_mul_2(&x);
1363*f9fbec18Smcpowers     if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)
1364*f9fbec18Smcpowers       goto CLEANUP;
1365*f9fbec18Smcpowers     s_mp_div_2(&x);
1366*f9fbec18Smcpowers 
1367*f9fbec18Smcpowers     /* Terminate the loop, if the quotient is zero */
1368*f9fbec18Smcpowers     if(mp_cmp_z(&t) == MP_EQ)
1369*f9fbec18Smcpowers       break;
1370*f9fbec18Smcpowers 
1371*f9fbec18Smcpowers     /* x = x - t       */
1372*f9fbec18Smcpowers     if((res = mp_sub(&x, &t, &x)) != MP_OKAY)
1373*f9fbec18Smcpowers       goto CLEANUP;
1374*f9fbec18Smcpowers 
1375*f9fbec18Smcpowers   }
1376*f9fbec18Smcpowers 
1377*f9fbec18Smcpowers   /* Copy result to output parameter */
1378*f9fbec18Smcpowers   mp_sub_d(&x, 1, &x);
1379*f9fbec18Smcpowers   s_mp_exch(&x, b);
1380*f9fbec18Smcpowers 
1381*f9fbec18Smcpowers  CLEANUP:
1382*f9fbec18Smcpowers   mp_clear(&x);
1383*f9fbec18Smcpowers  X:
1384*f9fbec18Smcpowers   mp_clear(&t);
1385*f9fbec18Smcpowers 
1386*f9fbec18Smcpowers   return res;
1387*f9fbec18Smcpowers 
1388*f9fbec18Smcpowers } /* end mp_sqrt() */
1389*f9fbec18Smcpowers 
1390*f9fbec18Smcpowers /* }}} */
1391*f9fbec18Smcpowers 
1392*f9fbec18Smcpowers /* }}} */
1393*f9fbec18Smcpowers 
1394*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
1395*f9fbec18Smcpowers /* {{{ Modular arithmetic */
1396*f9fbec18Smcpowers 
1397*f9fbec18Smcpowers #if MP_MODARITH
1398*f9fbec18Smcpowers /* {{{ mp_addmod(a, b, m, c) */
1399*f9fbec18Smcpowers 
1400*f9fbec18Smcpowers /*
1401*f9fbec18Smcpowers   mp_addmod(a, b, m, c)
1402*f9fbec18Smcpowers 
1403*f9fbec18Smcpowers   Compute c = (a + b) mod m
1404*f9fbec18Smcpowers  */
1405*f9fbec18Smcpowers 
1406*f9fbec18Smcpowers mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
1407*f9fbec18Smcpowers {
1408*f9fbec18Smcpowers   mp_err  res;
1409*f9fbec18Smcpowers 
1410*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
1411*f9fbec18Smcpowers 
1412*f9fbec18Smcpowers   if((res = mp_add(a, b, c)) != MP_OKAY)
1413*f9fbec18Smcpowers     return res;
1414*f9fbec18Smcpowers   if((res = mp_mod(c, m, c)) != MP_OKAY)
1415*f9fbec18Smcpowers     return res;
1416*f9fbec18Smcpowers 
1417*f9fbec18Smcpowers   return MP_OKAY;
1418*f9fbec18Smcpowers 
1419*f9fbec18Smcpowers }
1420*f9fbec18Smcpowers 
1421*f9fbec18Smcpowers /* }}} */
1422*f9fbec18Smcpowers 
1423*f9fbec18Smcpowers /* {{{ mp_submod(a, b, m, c) */
1424*f9fbec18Smcpowers 
1425*f9fbec18Smcpowers /*
1426*f9fbec18Smcpowers   mp_submod(a, b, m, c)
1427*f9fbec18Smcpowers 
1428*f9fbec18Smcpowers   Compute c = (a - b) mod m
1429*f9fbec18Smcpowers  */
1430*f9fbec18Smcpowers 
1431*f9fbec18Smcpowers mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
1432*f9fbec18Smcpowers {
1433*f9fbec18Smcpowers   mp_err  res;
1434*f9fbec18Smcpowers 
1435*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
1436*f9fbec18Smcpowers 
1437*f9fbec18Smcpowers   if((res = mp_sub(a, b, c)) != MP_OKAY)
1438*f9fbec18Smcpowers     return res;
1439*f9fbec18Smcpowers   if((res = mp_mod(c, m, c)) != MP_OKAY)
1440*f9fbec18Smcpowers     return res;
1441*f9fbec18Smcpowers 
1442*f9fbec18Smcpowers   return MP_OKAY;
1443*f9fbec18Smcpowers 
1444*f9fbec18Smcpowers }
1445*f9fbec18Smcpowers 
1446*f9fbec18Smcpowers /* }}} */
1447*f9fbec18Smcpowers 
1448*f9fbec18Smcpowers /* {{{ mp_mulmod(a, b, m, c) */
1449*f9fbec18Smcpowers 
1450*f9fbec18Smcpowers /*
1451*f9fbec18Smcpowers   mp_mulmod(a, b, m, c)
1452*f9fbec18Smcpowers 
1453*f9fbec18Smcpowers   Compute c = (a * b) mod m
1454*f9fbec18Smcpowers  */
1455*f9fbec18Smcpowers 
1456*f9fbec18Smcpowers mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
1457*f9fbec18Smcpowers {
1458*f9fbec18Smcpowers   mp_err  res;
1459*f9fbec18Smcpowers 
1460*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
1461*f9fbec18Smcpowers 
1462*f9fbec18Smcpowers   if((res = mp_mul(a, b, c)) != MP_OKAY)
1463*f9fbec18Smcpowers     return res;
1464*f9fbec18Smcpowers   if((res = mp_mod(c, m, c)) != MP_OKAY)
1465*f9fbec18Smcpowers     return res;
1466*f9fbec18Smcpowers 
1467*f9fbec18Smcpowers   return MP_OKAY;
1468*f9fbec18Smcpowers 
1469*f9fbec18Smcpowers }
1470*f9fbec18Smcpowers 
1471*f9fbec18Smcpowers /* }}} */
1472*f9fbec18Smcpowers 
1473*f9fbec18Smcpowers /* {{{ mp_sqrmod(a, m, c) */
1474*f9fbec18Smcpowers 
1475*f9fbec18Smcpowers #if MP_SQUARE
1476*f9fbec18Smcpowers mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c)
1477*f9fbec18Smcpowers {
1478*f9fbec18Smcpowers   mp_err  res;
1479*f9fbec18Smcpowers 
1480*f9fbec18Smcpowers   ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
1481*f9fbec18Smcpowers 
1482*f9fbec18Smcpowers   if((res = mp_sqr(a, c)) != MP_OKAY)
1483*f9fbec18Smcpowers     return res;
1484*f9fbec18Smcpowers   if((res = mp_mod(c, m, c)) != MP_OKAY)
1485*f9fbec18Smcpowers     return res;
1486*f9fbec18Smcpowers 
1487*f9fbec18Smcpowers   return MP_OKAY;
1488*f9fbec18Smcpowers 
1489*f9fbec18Smcpowers } /* end mp_sqrmod() */
1490*f9fbec18Smcpowers #endif
1491*f9fbec18Smcpowers 
1492*f9fbec18Smcpowers /* }}} */
1493*f9fbec18Smcpowers 
1494*f9fbec18Smcpowers /* {{{ s_mp_exptmod(a, b, m, c) */
1495*f9fbec18Smcpowers 
1496*f9fbec18Smcpowers /*
1497*f9fbec18Smcpowers   s_mp_exptmod(a, b, m, c)
1498*f9fbec18Smcpowers 
1499*f9fbec18Smcpowers   Compute c = (a ** b) mod m.  Uses a standard square-and-multiply
1500*f9fbec18Smcpowers   method with modular reductions at each step. (This is basically the
1501*f9fbec18Smcpowers   same code as mp_expt(), except for the addition of the reductions)
1502*f9fbec18Smcpowers 
1503*f9fbec18Smcpowers   The modular reductions are done using Barrett's algorithm (see
1504*f9fbec18Smcpowers   s_mp_reduce() below for details)
1505*f9fbec18Smcpowers  */
1506*f9fbec18Smcpowers 
1507*f9fbec18Smcpowers mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
1508*f9fbec18Smcpowers {
1509*f9fbec18Smcpowers   mp_int   s, x, mu;
1510*f9fbec18Smcpowers   mp_err   res;
1511*f9fbec18Smcpowers   mp_digit d;
1512*f9fbec18Smcpowers   int      dig, bit;
1513*f9fbec18Smcpowers 
1514*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
1515*f9fbec18Smcpowers 
1516*f9fbec18Smcpowers   if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
1517*f9fbec18Smcpowers     return MP_RANGE;
1518*f9fbec18Smcpowers 
1519*f9fbec18Smcpowers   if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
1520*f9fbec18Smcpowers     return res;
1521*f9fbec18Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY ||
1522*f9fbec18Smcpowers      (res = mp_mod(&x, m, &x)) != MP_OKAY)
1523*f9fbec18Smcpowers     goto X;
1524*f9fbec18Smcpowers   if((res = mp_init(&mu, FLAG(a))) != MP_OKAY)
1525*f9fbec18Smcpowers     goto MU;
1526*f9fbec18Smcpowers 
1527*f9fbec18Smcpowers   mp_set(&s, 1);
1528*f9fbec18Smcpowers 
1529*f9fbec18Smcpowers   /* mu = b^2k / m */
1530*f9fbec18Smcpowers   s_mp_add_d(&mu, 1);
1531*f9fbec18Smcpowers   s_mp_lshd(&mu, 2 * USED(m));
1532*f9fbec18Smcpowers   if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)
1533*f9fbec18Smcpowers     goto CLEANUP;
1534*f9fbec18Smcpowers 
1535*f9fbec18Smcpowers   /* Loop over digits of b in ascending order, except highest order */
1536*f9fbec18Smcpowers   for(dig = 0; dig < (USED(b) - 1); dig++) {
1537*f9fbec18Smcpowers     d = DIGIT(b, dig);
1538*f9fbec18Smcpowers 
1539*f9fbec18Smcpowers     /* Loop over the bits of the lower-order digits */
1540*f9fbec18Smcpowers     for(bit = 0; bit < DIGIT_BIT; bit++) {
1541*f9fbec18Smcpowers       if(d & 1) {
1542*f9fbec18Smcpowers 	if((res = s_mp_mul(&s, &x)) != MP_OKAY)
1543*f9fbec18Smcpowers 	  goto CLEANUP;
1544*f9fbec18Smcpowers 	if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
1545*f9fbec18Smcpowers 	  goto CLEANUP;
1546*f9fbec18Smcpowers       }
1547*f9fbec18Smcpowers 
1548*f9fbec18Smcpowers       d >>= 1;
1549*f9fbec18Smcpowers 
1550*f9fbec18Smcpowers       if((res = s_mp_sqr(&x)) != MP_OKAY)
1551*f9fbec18Smcpowers 	goto CLEANUP;
1552*f9fbec18Smcpowers       if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
1553*f9fbec18Smcpowers 	goto CLEANUP;
1554*f9fbec18Smcpowers     }
1555*f9fbec18Smcpowers   }
1556*f9fbec18Smcpowers 
1557*f9fbec18Smcpowers   /* Now do the last digit... */
1558*f9fbec18Smcpowers   d = DIGIT(b, dig);
1559*f9fbec18Smcpowers 
1560*f9fbec18Smcpowers   while(d) {
1561*f9fbec18Smcpowers     if(d & 1) {
1562*f9fbec18Smcpowers       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
1563*f9fbec18Smcpowers 	goto CLEANUP;
1564*f9fbec18Smcpowers       if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
1565*f9fbec18Smcpowers 	goto CLEANUP;
1566*f9fbec18Smcpowers     }
1567*f9fbec18Smcpowers 
1568*f9fbec18Smcpowers     d >>= 1;
1569*f9fbec18Smcpowers 
1570*f9fbec18Smcpowers     if((res = s_mp_sqr(&x)) != MP_OKAY)
1571*f9fbec18Smcpowers       goto CLEANUP;
1572*f9fbec18Smcpowers     if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
1573*f9fbec18Smcpowers       goto CLEANUP;
1574*f9fbec18Smcpowers   }
1575*f9fbec18Smcpowers 
1576*f9fbec18Smcpowers   s_mp_exch(&s, c);
1577*f9fbec18Smcpowers 
1578*f9fbec18Smcpowers  CLEANUP:
1579*f9fbec18Smcpowers   mp_clear(&mu);
1580*f9fbec18Smcpowers  MU:
1581*f9fbec18Smcpowers   mp_clear(&x);
1582*f9fbec18Smcpowers  X:
1583*f9fbec18Smcpowers   mp_clear(&s);
1584*f9fbec18Smcpowers 
1585*f9fbec18Smcpowers   return res;
1586*f9fbec18Smcpowers 
1587*f9fbec18Smcpowers } /* end s_mp_exptmod() */
1588*f9fbec18Smcpowers 
1589*f9fbec18Smcpowers /* }}} */
1590*f9fbec18Smcpowers 
1591*f9fbec18Smcpowers /* {{{ mp_exptmod_d(a, d, m, c) */
1592*f9fbec18Smcpowers 
1593*f9fbec18Smcpowers mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c)
1594*f9fbec18Smcpowers {
1595*f9fbec18Smcpowers   mp_int   s, x;
1596*f9fbec18Smcpowers   mp_err   res;
1597*f9fbec18Smcpowers 
1598*f9fbec18Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
1599*f9fbec18Smcpowers 
1600*f9fbec18Smcpowers   if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
1601*f9fbec18Smcpowers     return res;
1602*f9fbec18Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY)
1603*f9fbec18Smcpowers     goto X;
1604*f9fbec18Smcpowers 
1605*f9fbec18Smcpowers   mp_set(&s, 1);
1606*f9fbec18Smcpowers 
1607*f9fbec18Smcpowers   while(d != 0) {
1608*f9fbec18Smcpowers     if(d & 1) {
1609*f9fbec18Smcpowers       if((res = s_mp_mul(&s, &x)) != MP_OKAY ||
1610*f9fbec18Smcpowers 	 (res = mp_mod(&s, m, &s)) != MP_OKAY)
1611*f9fbec18Smcpowers 	goto CLEANUP;
1612*f9fbec18Smcpowers     }
1613*f9fbec18Smcpowers 
1614*f9fbec18Smcpowers     d /= 2;
1615*f9fbec18Smcpowers 
1616*f9fbec18Smcpowers     if((res = s_mp_sqr(&x)) != MP_OKAY ||
1617*f9fbec18Smcpowers        (res = mp_mod(&x, m, &x)) != MP_OKAY)
1618*f9fbec18Smcpowers       goto CLEANUP;
1619*f9fbec18Smcpowers   }
1620*f9fbec18Smcpowers 
1621*f9fbec18Smcpowers   s_mp_exch(&s, c);
1622*f9fbec18Smcpowers 
1623*f9fbec18Smcpowers CLEANUP:
1624*f9fbec18Smcpowers   mp_clear(&x);
1625*f9fbec18Smcpowers X:
1626*f9fbec18Smcpowers   mp_clear(&s);
1627*f9fbec18Smcpowers 
1628*f9fbec18Smcpowers   return res;
1629*f9fbec18Smcpowers 
1630*f9fbec18Smcpowers } /* end mp_exptmod_d() */
1631*f9fbec18Smcpowers 
1632*f9fbec18Smcpowers /* }}} */
1633*f9fbec18Smcpowers #endif /* if MP_MODARITH */
1634*f9fbec18Smcpowers 
1635*f9fbec18Smcpowers /* }}} */
1636*f9fbec18Smcpowers 
1637*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
1638*f9fbec18Smcpowers /* {{{ Comparison functions */
1639*f9fbec18Smcpowers 
1640*f9fbec18Smcpowers /* {{{ mp_cmp_z(a) */
1641*f9fbec18Smcpowers 
1642*f9fbec18Smcpowers /*
1643*f9fbec18Smcpowers   mp_cmp_z(a)
1644*f9fbec18Smcpowers 
1645*f9fbec18Smcpowers   Compare a <=> 0.  Returns <0 if a<0, 0 if a=0, >0 if a>0.
1646*f9fbec18Smcpowers  */
1647*f9fbec18Smcpowers 
1648*f9fbec18Smcpowers int    mp_cmp_z(const mp_int *a)
1649*f9fbec18Smcpowers {
1650*f9fbec18Smcpowers   if(SIGN(a) == NEG)
1651*f9fbec18Smcpowers     return MP_LT;
1652*f9fbec18Smcpowers   else if(USED(a) == 1 && DIGIT(a, 0) == 0)
1653*f9fbec18Smcpowers     return MP_EQ;
1654*f9fbec18Smcpowers   else
1655*f9fbec18Smcpowers     return MP_GT;
1656*f9fbec18Smcpowers 
1657*f9fbec18Smcpowers } /* end mp_cmp_z() */
1658*f9fbec18Smcpowers 
1659*f9fbec18Smcpowers /* }}} */
1660*f9fbec18Smcpowers 
1661*f9fbec18Smcpowers /* {{{ mp_cmp_d(a, d) */
1662*f9fbec18Smcpowers 
1663*f9fbec18Smcpowers /*
1664*f9fbec18Smcpowers   mp_cmp_d(a, d)
1665*f9fbec18Smcpowers 
1666*f9fbec18Smcpowers   Compare a <=> d.  Returns <0 if a<d, 0 if a=d, >0 if a>d
1667*f9fbec18Smcpowers  */
1668*f9fbec18Smcpowers 
1669*f9fbec18Smcpowers int    mp_cmp_d(const mp_int *a, mp_digit d)
1670*f9fbec18Smcpowers {
1671*f9fbec18Smcpowers   ARGCHK(a != NULL, MP_EQ);
1672*f9fbec18Smcpowers 
1673*f9fbec18Smcpowers   if(SIGN(a) == NEG)
1674*f9fbec18Smcpowers     return MP_LT;
1675*f9fbec18Smcpowers 
1676*f9fbec18Smcpowers   return s_mp_cmp_d(a, d);
1677*f9fbec18Smcpowers 
1678*f9fbec18Smcpowers } /* end mp_cmp_d() */
1679*f9fbec18Smcpowers 
1680*f9fbec18Smcpowers /* }}} */
1681*f9fbec18Smcpowers 
1682*f9fbec18Smcpowers /* {{{ mp_cmp(a, b) */
1683*f9fbec18Smcpowers 
1684*f9fbec18Smcpowers int    mp_cmp(const mp_int *a, const mp_int *b)
1685*f9fbec18Smcpowers {
1686*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_EQ);
1687*f9fbec18Smcpowers 
1688*f9fbec18Smcpowers   if(SIGN(a) == SIGN(b)) {
1689*f9fbec18Smcpowers     int  mag;
1690*f9fbec18Smcpowers 
1691*f9fbec18Smcpowers     if((mag = s_mp_cmp(a, b)) == MP_EQ)
1692*f9fbec18Smcpowers       return MP_EQ;
1693*f9fbec18Smcpowers 
1694*f9fbec18Smcpowers     if(SIGN(a) == ZPOS)
1695*f9fbec18Smcpowers       return mag;
1696*f9fbec18Smcpowers     else
1697*f9fbec18Smcpowers       return -mag;
1698*f9fbec18Smcpowers 
1699*f9fbec18Smcpowers   } else if(SIGN(a) == ZPOS) {
1700*f9fbec18Smcpowers     return MP_GT;
1701*f9fbec18Smcpowers   } else {
1702*f9fbec18Smcpowers     return MP_LT;
1703*f9fbec18Smcpowers   }
1704*f9fbec18Smcpowers 
1705*f9fbec18Smcpowers } /* end mp_cmp() */
1706*f9fbec18Smcpowers 
1707*f9fbec18Smcpowers /* }}} */
1708*f9fbec18Smcpowers 
1709*f9fbec18Smcpowers /* {{{ mp_cmp_mag(a, b) */
1710*f9fbec18Smcpowers 
1711*f9fbec18Smcpowers /*
1712*f9fbec18Smcpowers   mp_cmp_mag(a, b)
1713*f9fbec18Smcpowers 
1714*f9fbec18Smcpowers   Compares |a| <=> |b|, and returns an appropriate comparison result
1715*f9fbec18Smcpowers  */
1716*f9fbec18Smcpowers 
1717*f9fbec18Smcpowers int    mp_cmp_mag(mp_int *a, mp_int *b)
1718*f9fbec18Smcpowers {
1719*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL, MP_EQ);
1720*f9fbec18Smcpowers 
1721*f9fbec18Smcpowers   return s_mp_cmp(a, b);
1722*f9fbec18Smcpowers 
1723*f9fbec18Smcpowers } /* end mp_cmp_mag() */
1724*f9fbec18Smcpowers 
1725*f9fbec18Smcpowers /* }}} */
1726*f9fbec18Smcpowers 
1727*f9fbec18Smcpowers /* {{{ mp_cmp_int(a, z, kmflag) */
1728*f9fbec18Smcpowers 
1729*f9fbec18Smcpowers /*
1730*f9fbec18Smcpowers   This just converts z to an mp_int, and uses the existing comparison
1731*f9fbec18Smcpowers   routines.  This is sort of inefficient, but it's not clear to me how
1732*f9fbec18Smcpowers   frequently this wil get used anyway.  For small positive constants,
1733*f9fbec18Smcpowers   you can always use mp_cmp_d(), and for zero, there is mp_cmp_z().
1734*f9fbec18Smcpowers  */
1735*f9fbec18Smcpowers int    mp_cmp_int(const mp_int *a, long z, int kmflag)
1736*f9fbec18Smcpowers {
1737*f9fbec18Smcpowers   mp_int  tmp;
1738*f9fbec18Smcpowers   int     out;
1739*f9fbec18Smcpowers 
1740*f9fbec18Smcpowers   ARGCHK(a != NULL, MP_EQ);
1741*f9fbec18Smcpowers 
1742*f9fbec18Smcpowers   mp_init(&tmp, kmflag); mp_set_int(&tmp, z);
1743*f9fbec18Smcpowers   out = mp_cmp(a, &tmp);
1744*f9fbec18Smcpowers   mp_clear(&tmp);
1745*f9fbec18Smcpowers 
1746*f9fbec18Smcpowers   return out;
1747*f9fbec18Smcpowers 
1748*f9fbec18Smcpowers } /* end mp_cmp_int() */
1749*f9fbec18Smcpowers 
1750*f9fbec18Smcpowers /* }}} */
1751*f9fbec18Smcpowers 
1752*f9fbec18Smcpowers /* {{{ mp_isodd(a) */
1753*f9fbec18Smcpowers 
1754*f9fbec18Smcpowers /*
1755*f9fbec18Smcpowers   mp_isodd(a)
1756*f9fbec18Smcpowers 
1757*f9fbec18Smcpowers   Returns a true (non-zero) value if a is odd, false (zero) otherwise.
1758*f9fbec18Smcpowers  */
1759*f9fbec18Smcpowers int    mp_isodd(const mp_int *a)
1760*f9fbec18Smcpowers {
1761*f9fbec18Smcpowers   ARGCHK(a != NULL, 0);
1762*f9fbec18Smcpowers 
1763*f9fbec18Smcpowers   return (int)(DIGIT(a, 0) & 1);
1764*f9fbec18Smcpowers 
1765*f9fbec18Smcpowers } /* end mp_isodd() */
1766*f9fbec18Smcpowers 
1767*f9fbec18Smcpowers /* }}} */
1768*f9fbec18Smcpowers 
1769*f9fbec18Smcpowers /* {{{ mp_iseven(a) */
1770*f9fbec18Smcpowers 
1771*f9fbec18Smcpowers int    mp_iseven(const mp_int *a)
1772*f9fbec18Smcpowers {
1773*f9fbec18Smcpowers   return !mp_isodd(a);
1774*f9fbec18Smcpowers 
1775*f9fbec18Smcpowers } /* end mp_iseven() */
1776*f9fbec18Smcpowers 
1777*f9fbec18Smcpowers /* }}} */
1778*f9fbec18Smcpowers 
1779*f9fbec18Smcpowers /* }}} */
1780*f9fbec18Smcpowers 
1781*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
1782*f9fbec18Smcpowers /* {{{ Number theoretic functions */
1783*f9fbec18Smcpowers 
1784*f9fbec18Smcpowers #if MP_NUMTH
1785*f9fbec18Smcpowers /* {{{ mp_gcd(a, b, c) */
1786*f9fbec18Smcpowers 
1787*f9fbec18Smcpowers /*
1788*f9fbec18Smcpowers   Like the old mp_gcd() function, except computes the GCD using the
1789*f9fbec18Smcpowers   binary algorithm due to Josef Stein in 1961 (via Knuth).
1790*f9fbec18Smcpowers  */
1791*f9fbec18Smcpowers mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c)
1792*f9fbec18Smcpowers {
1793*f9fbec18Smcpowers   mp_err   res;
1794*f9fbec18Smcpowers   mp_int   u, v, t;
1795*f9fbec18Smcpowers   mp_size  k = 0;
1796*f9fbec18Smcpowers 
1797*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
1798*f9fbec18Smcpowers 
1799*f9fbec18Smcpowers   if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)
1800*f9fbec18Smcpowers       return MP_RANGE;
1801*f9fbec18Smcpowers   if(mp_cmp_z(a) == MP_EQ) {
1802*f9fbec18Smcpowers     return mp_copy(b, c);
1803*f9fbec18Smcpowers   } else if(mp_cmp_z(b) == MP_EQ) {
1804*f9fbec18Smcpowers     return mp_copy(a, c);
1805*f9fbec18Smcpowers   }
1806*f9fbec18Smcpowers 
1807*f9fbec18Smcpowers   if((res = mp_init(&t, FLAG(a))) != MP_OKAY)
1808*f9fbec18Smcpowers     return res;
1809*f9fbec18Smcpowers   if((res = mp_init_copy(&u, a)) != MP_OKAY)
1810*f9fbec18Smcpowers     goto U;
1811*f9fbec18Smcpowers   if((res = mp_init_copy(&v, b)) != MP_OKAY)
1812*f9fbec18Smcpowers     goto V;
1813*f9fbec18Smcpowers 
1814*f9fbec18Smcpowers   SIGN(&u) = ZPOS;
1815*f9fbec18Smcpowers   SIGN(&v) = ZPOS;
1816*f9fbec18Smcpowers 
1817*f9fbec18Smcpowers   /* Divide out common factors of 2 until at least 1 of a, b is even */
1818*f9fbec18Smcpowers   while(mp_iseven(&u) && mp_iseven(&v)) {
1819*f9fbec18Smcpowers     s_mp_div_2(&u);
1820*f9fbec18Smcpowers     s_mp_div_2(&v);
1821*f9fbec18Smcpowers     ++k;
1822*f9fbec18Smcpowers   }
1823*f9fbec18Smcpowers 
1824*f9fbec18Smcpowers   /* Initialize t */
1825*f9fbec18Smcpowers   if(mp_isodd(&u)) {
1826*f9fbec18Smcpowers     if((res = mp_copy(&v, &t)) != MP_OKAY)
1827*f9fbec18Smcpowers       goto CLEANUP;
1828*f9fbec18Smcpowers 
1829*f9fbec18Smcpowers     /* t = -v */
1830*f9fbec18Smcpowers     if(SIGN(&v) == ZPOS)
1831*f9fbec18Smcpowers       SIGN(&t) = NEG;
1832*f9fbec18Smcpowers     else
1833*f9fbec18Smcpowers       SIGN(&t) = ZPOS;
1834*f9fbec18Smcpowers 
1835*f9fbec18Smcpowers   } else {
1836*f9fbec18Smcpowers     if((res = mp_copy(&u, &t)) != MP_OKAY)
1837*f9fbec18Smcpowers       goto CLEANUP;
1838*f9fbec18Smcpowers 
1839*f9fbec18Smcpowers   }
1840*f9fbec18Smcpowers 
1841*f9fbec18Smcpowers   for(;;) {
1842*f9fbec18Smcpowers     while(mp_iseven(&t)) {
1843*f9fbec18Smcpowers       s_mp_div_2(&t);
1844*f9fbec18Smcpowers     }
1845*f9fbec18Smcpowers 
1846*f9fbec18Smcpowers     if(mp_cmp_z(&t) == MP_GT) {
1847*f9fbec18Smcpowers       if((res = mp_copy(&t, &u)) != MP_OKAY)
1848*f9fbec18Smcpowers 	goto CLEANUP;
1849*f9fbec18Smcpowers 
1850*f9fbec18Smcpowers     } else {
1851*f9fbec18Smcpowers       if((res = mp_copy(&t, &v)) != MP_OKAY)
1852*f9fbec18Smcpowers 	goto CLEANUP;
1853*f9fbec18Smcpowers 
1854*f9fbec18Smcpowers       /* v = -t */
1855*f9fbec18Smcpowers       if(SIGN(&t) == ZPOS)
1856*f9fbec18Smcpowers 	SIGN(&v) = NEG;
1857*f9fbec18Smcpowers       else
1858*f9fbec18Smcpowers 	SIGN(&v) = ZPOS;
1859*f9fbec18Smcpowers     }
1860*f9fbec18Smcpowers 
1861*f9fbec18Smcpowers     if((res = mp_sub(&u, &v, &t)) != MP_OKAY)
1862*f9fbec18Smcpowers       goto CLEANUP;
1863*f9fbec18Smcpowers 
1864*f9fbec18Smcpowers     if(s_mp_cmp_d(&t, 0) == MP_EQ)
1865*f9fbec18Smcpowers       break;
1866*f9fbec18Smcpowers   }
1867*f9fbec18Smcpowers 
1868*f9fbec18Smcpowers   s_mp_2expt(&v, k);       /* v = 2^k   */
1869*f9fbec18Smcpowers   res = mp_mul(&u, &v, c); /* c = u * v */
1870*f9fbec18Smcpowers 
1871*f9fbec18Smcpowers  CLEANUP:
1872*f9fbec18Smcpowers   mp_clear(&v);
1873*f9fbec18Smcpowers  V:
1874*f9fbec18Smcpowers   mp_clear(&u);
1875*f9fbec18Smcpowers  U:
1876*f9fbec18Smcpowers   mp_clear(&t);
1877*f9fbec18Smcpowers 
1878*f9fbec18Smcpowers   return res;
1879*f9fbec18Smcpowers 
1880*f9fbec18Smcpowers } /* end mp_gcd() */
1881*f9fbec18Smcpowers 
1882*f9fbec18Smcpowers /* }}} */
1883*f9fbec18Smcpowers 
1884*f9fbec18Smcpowers /* {{{ mp_lcm(a, b, c) */
1885*f9fbec18Smcpowers 
1886*f9fbec18Smcpowers /* We compute the least common multiple using the rule:
1887*f9fbec18Smcpowers 
1888*f9fbec18Smcpowers    ab = [a, b](a, b)
1889*f9fbec18Smcpowers 
1890*f9fbec18Smcpowers    ... by computing the product, and dividing out the gcd.
1891*f9fbec18Smcpowers  */
1892*f9fbec18Smcpowers 
1893*f9fbec18Smcpowers mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c)
1894*f9fbec18Smcpowers {
1895*f9fbec18Smcpowers   mp_int  gcd, prod;
1896*f9fbec18Smcpowers   mp_err  res;
1897*f9fbec18Smcpowers 
1898*f9fbec18Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
1899*f9fbec18Smcpowers 
1900*f9fbec18Smcpowers   /* Set up temporaries */
1901*f9fbec18Smcpowers   if((res = mp_init(&gcd, FLAG(a))) != MP_OKAY)
1902*f9fbec18Smcpowers     return res;
1903*f9fbec18Smcpowers   if((res = mp_init(&prod, FLAG(a))) != MP_OKAY)
1904*f9fbec18Smcpowers     goto GCD;
1905*f9fbec18Smcpowers 
1906*f9fbec18Smcpowers   if((res = mp_mul(a, b, &prod)) != MP_OKAY)
1907*f9fbec18Smcpowers     goto CLEANUP;
1908*f9fbec18Smcpowers   if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)
1909*f9fbec18Smcpowers     goto CLEANUP;
1910*f9fbec18Smcpowers 
1911*f9fbec18Smcpowers   res = mp_div(&prod, &gcd, c, NULL);
1912*f9fbec18Smcpowers 
1913*f9fbec18Smcpowers  CLEANUP:
1914*f9fbec18Smcpowers   mp_clear(&prod);
1915*f9fbec18Smcpowers  GCD:
1916*f9fbec18Smcpowers   mp_clear(&gcd);
1917*f9fbec18Smcpowers 
1918*f9fbec18Smcpowers   return res;
1919*f9fbec18Smcpowers 
1920*f9fbec18Smcpowers } /* end mp_lcm() */
1921*f9fbec18Smcpowers 
1922*f9fbec18Smcpowers /* }}} */
1923*f9fbec18Smcpowers 
1924*f9fbec18Smcpowers /* {{{ mp_xgcd(a, b, g, x, y) */
1925*f9fbec18Smcpowers 
1926*f9fbec18Smcpowers /*
1927*f9fbec18Smcpowers   mp_xgcd(a, b, g, x, y)
1928*f9fbec18Smcpowers 
1929*f9fbec18Smcpowers   Compute g = (a, b) and values x and y satisfying Bezout's identity
1930*f9fbec18Smcpowers   (that is, ax + by = g).  This uses the binary extended GCD algorithm
1931*f9fbec18Smcpowers   based on the Stein algorithm used for mp_gcd()
1932*f9fbec18Smcpowers   See algorithm 14.61 in Handbook of Applied Cryptogrpahy.
1933*f9fbec18Smcpowers  */
1934*f9fbec18Smcpowers 
1935*f9fbec18Smcpowers mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y)
1936*f9fbec18Smcpowers {
1937*f9fbec18Smcpowers   mp_int   gx, xc, yc, u, v, A, B, C, D;
1938*f9fbec18Smcpowers   mp_int  *clean[9];
1939*f9fbec18Smcpowers   mp_err   res;
1940*f9fbec18Smcpowers   int      last = -1;
1941*f9fbec18Smcpowers 
1942*f9fbec18Smcpowers   if(mp_cmp_z(b) == 0)
1943*f9fbec18Smcpowers     return MP_RANGE;
1944*f9fbec18Smcpowers 
1945*f9fbec18Smcpowers   /* Initialize all these variables we need */
1946*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&u, FLAG(a)) );
1947*f9fbec18Smcpowers   clean[++last] = &u;
1948*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&v, FLAG(a)) );
1949*f9fbec18Smcpowers   clean[++last] = &v;
1950*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&gx, FLAG(a)) );
1951*f9fbec18Smcpowers   clean[++last] = &gx;
1952*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&A, FLAG(a)) );
1953*f9fbec18Smcpowers   clean[++last] = &A;
1954*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&B, FLAG(a)) );
1955*f9fbec18Smcpowers   clean[++last] = &B;
1956*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&C, FLAG(a)) );
1957*f9fbec18Smcpowers   clean[++last] = &C;
1958*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&D, FLAG(a)) );
1959*f9fbec18Smcpowers   clean[++last] = &D;
1960*f9fbec18Smcpowers   MP_CHECKOK( mp_init_copy(&xc, a) );
1961*f9fbec18Smcpowers   clean[++last] = &xc;
1962*f9fbec18Smcpowers   mp_abs(&xc, &xc);
1963*f9fbec18Smcpowers   MP_CHECKOK( mp_init_copy(&yc, b) );
1964*f9fbec18Smcpowers   clean[++last] = &yc;
1965*f9fbec18Smcpowers   mp_abs(&yc, &yc);
1966*f9fbec18Smcpowers 
1967*f9fbec18Smcpowers   mp_set(&gx, 1);
1968*f9fbec18Smcpowers 
1969*f9fbec18Smcpowers   /* Divide by two until at least one of them is odd */
1970*f9fbec18Smcpowers   while(mp_iseven(&xc) && mp_iseven(&yc)) {
1971*f9fbec18Smcpowers     mp_size nx = mp_trailing_zeros(&xc);
1972*f9fbec18Smcpowers     mp_size ny = mp_trailing_zeros(&yc);
1973*f9fbec18Smcpowers     mp_size n  = MP_MIN(nx, ny);
1974*f9fbec18Smcpowers     s_mp_div_2d(&xc,n);
1975*f9fbec18Smcpowers     s_mp_div_2d(&yc,n);
1976*f9fbec18Smcpowers     MP_CHECKOK( s_mp_mul_2d(&gx,n) );
1977*f9fbec18Smcpowers   }
1978*f9fbec18Smcpowers 
1979*f9fbec18Smcpowers   mp_copy(&xc, &u);
1980*f9fbec18Smcpowers   mp_copy(&yc, &v);
1981*f9fbec18Smcpowers   mp_set(&A, 1); mp_set(&D, 1);
1982*f9fbec18Smcpowers 
1983*f9fbec18Smcpowers   /* Loop through binary GCD algorithm */
1984*f9fbec18Smcpowers   do {
1985*f9fbec18Smcpowers     while(mp_iseven(&u)) {
1986*f9fbec18Smcpowers       s_mp_div_2(&u);
1987*f9fbec18Smcpowers 
1988*f9fbec18Smcpowers       if(mp_iseven(&A) && mp_iseven(&B)) {
1989*f9fbec18Smcpowers 	s_mp_div_2(&A); s_mp_div_2(&B);
1990*f9fbec18Smcpowers       } else {
1991*f9fbec18Smcpowers 	MP_CHECKOK( mp_add(&A, &yc, &A) );
1992*f9fbec18Smcpowers 	s_mp_div_2(&A);
1993*f9fbec18Smcpowers 	MP_CHECKOK( mp_sub(&B, &xc, &B) );
1994*f9fbec18Smcpowers 	s_mp_div_2(&B);
1995*f9fbec18Smcpowers       }
1996*f9fbec18Smcpowers     }
1997*f9fbec18Smcpowers 
1998*f9fbec18Smcpowers     while(mp_iseven(&v)) {
1999*f9fbec18Smcpowers       s_mp_div_2(&v);
2000*f9fbec18Smcpowers 
2001*f9fbec18Smcpowers       if(mp_iseven(&C) && mp_iseven(&D)) {
2002*f9fbec18Smcpowers 	s_mp_div_2(&C); s_mp_div_2(&D);
2003*f9fbec18Smcpowers       } else {
2004*f9fbec18Smcpowers 	MP_CHECKOK( mp_add(&C, &yc, &C) );
2005*f9fbec18Smcpowers 	s_mp_div_2(&C);
2006*f9fbec18Smcpowers 	MP_CHECKOK( mp_sub(&D, &xc, &D) );
2007*f9fbec18Smcpowers 	s_mp_div_2(&D);
2008*f9fbec18Smcpowers       }
2009*f9fbec18Smcpowers     }
2010*f9fbec18Smcpowers 
2011*f9fbec18Smcpowers     if(mp_cmp(&u, &v) >= 0) {
2012*f9fbec18Smcpowers       MP_CHECKOK( mp_sub(&u, &v, &u) );
2013*f9fbec18Smcpowers       MP_CHECKOK( mp_sub(&A, &C, &A) );
2014*f9fbec18Smcpowers       MP_CHECKOK( mp_sub(&B, &D, &B) );
2015*f9fbec18Smcpowers     } else {
2016*f9fbec18Smcpowers       MP_CHECKOK( mp_sub(&v, &u, &v) );
2017*f9fbec18Smcpowers       MP_CHECKOK( mp_sub(&C, &A, &C) );
2018*f9fbec18Smcpowers       MP_CHECKOK( mp_sub(&D, &B, &D) );
2019*f9fbec18Smcpowers     }
2020*f9fbec18Smcpowers   } while (mp_cmp_z(&u) != 0);
2021*f9fbec18Smcpowers 
2022*f9fbec18Smcpowers   /* copy results to output */
2023*f9fbec18Smcpowers   if(x)
2024*f9fbec18Smcpowers     MP_CHECKOK( mp_copy(&C, x) );
2025*f9fbec18Smcpowers 
2026*f9fbec18Smcpowers   if(y)
2027*f9fbec18Smcpowers     MP_CHECKOK( mp_copy(&D, y) );
2028*f9fbec18Smcpowers 
2029*f9fbec18Smcpowers   if(g)
2030*f9fbec18Smcpowers     MP_CHECKOK( mp_mul(&gx, &v, g) );
2031*f9fbec18Smcpowers 
2032*f9fbec18Smcpowers  CLEANUP:
2033*f9fbec18Smcpowers   while(last >= 0)
2034*f9fbec18Smcpowers     mp_clear(clean[last--]);
2035*f9fbec18Smcpowers 
2036*f9fbec18Smcpowers   return res;
2037*f9fbec18Smcpowers 
2038*f9fbec18Smcpowers } /* end mp_xgcd() */
2039*f9fbec18Smcpowers 
2040*f9fbec18Smcpowers /* }}} */
2041*f9fbec18Smcpowers 
2042*f9fbec18Smcpowers mp_size mp_trailing_zeros(const mp_int *mp)
2043*f9fbec18Smcpowers {
2044*f9fbec18Smcpowers   mp_digit d;
2045*f9fbec18Smcpowers   mp_size  n = 0;
2046*f9fbec18Smcpowers   int      ix;
2047*f9fbec18Smcpowers 
2048*f9fbec18Smcpowers   if (!mp || !MP_DIGITS(mp) || !mp_cmp_z(mp))
2049*f9fbec18Smcpowers     return n;
2050*f9fbec18Smcpowers 
2051*f9fbec18Smcpowers   for (ix = 0; !(d = MP_DIGIT(mp,ix)) && (ix < MP_USED(mp)); ++ix)
2052*f9fbec18Smcpowers     n += MP_DIGIT_BIT;
2053*f9fbec18Smcpowers   if (!d)
2054*f9fbec18Smcpowers     return 0;	/* shouldn't happen, but ... */
2055*f9fbec18Smcpowers #if !defined(MP_USE_UINT_DIGIT)
2056*f9fbec18Smcpowers   if (!(d & 0xffffffffU)) {
2057*f9fbec18Smcpowers     d >>= 32;
2058*f9fbec18Smcpowers     n  += 32;
2059*f9fbec18Smcpowers   }
2060*f9fbec18Smcpowers #endif
2061*f9fbec18Smcpowers   if (!(d & 0xffffU)) {
2062*f9fbec18Smcpowers     d >>= 16;
2063*f9fbec18Smcpowers     n  += 16;
2064*f9fbec18Smcpowers   }
2065*f9fbec18Smcpowers   if (!(d & 0xffU)) {
2066*f9fbec18Smcpowers     d >>= 8;
2067*f9fbec18Smcpowers     n  += 8;
2068*f9fbec18Smcpowers   }
2069*f9fbec18Smcpowers   if (!(d & 0xfU)) {
2070*f9fbec18Smcpowers     d >>= 4;
2071*f9fbec18Smcpowers     n  += 4;
2072*f9fbec18Smcpowers   }
2073*f9fbec18Smcpowers   if (!(d & 0x3U)) {
2074*f9fbec18Smcpowers     d >>= 2;
2075*f9fbec18Smcpowers     n  += 2;
2076*f9fbec18Smcpowers   }
2077*f9fbec18Smcpowers   if (!(d & 0x1U)) {
2078*f9fbec18Smcpowers     d >>= 1;
2079*f9fbec18Smcpowers     n  += 1;
2080*f9fbec18Smcpowers   }
2081*f9fbec18Smcpowers #if MP_ARGCHK == 2
2082*f9fbec18Smcpowers   assert(0 != (d & 1));
2083*f9fbec18Smcpowers #endif
2084*f9fbec18Smcpowers   return n;
2085*f9fbec18Smcpowers }
2086*f9fbec18Smcpowers 
2087*f9fbec18Smcpowers /* Given a and prime p, computes c and k such that a*c == 2**k (mod p).
2088*f9fbec18Smcpowers ** Returns k (positive) or error (negative).
2089*f9fbec18Smcpowers ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
2090*f9fbec18Smcpowers ** by Richard Schroeppel (a.k.a. Captain Nemo).
2091*f9fbec18Smcpowers */
2092*f9fbec18Smcpowers mp_err s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
2093*f9fbec18Smcpowers {
2094*f9fbec18Smcpowers   mp_err res;
2095*f9fbec18Smcpowers   mp_err k    = 0;
2096*f9fbec18Smcpowers   mp_int d, f, g;
2097*f9fbec18Smcpowers 
2098*f9fbec18Smcpowers   ARGCHK(a && p && c, MP_BADARG);
2099*f9fbec18Smcpowers 
2100*f9fbec18Smcpowers   MP_DIGITS(&d) = 0;
2101*f9fbec18Smcpowers   MP_DIGITS(&f) = 0;
2102*f9fbec18Smcpowers   MP_DIGITS(&g) = 0;
2103*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&d, FLAG(a)) );
2104*f9fbec18Smcpowers   MP_CHECKOK( mp_init_copy(&f, a) );	/* f = a */
2105*f9fbec18Smcpowers   MP_CHECKOK( mp_init_copy(&g, p) );	/* g = p */
2106*f9fbec18Smcpowers 
2107*f9fbec18Smcpowers   mp_set(c, 1);
2108*f9fbec18Smcpowers   mp_zero(&d);
2109*f9fbec18Smcpowers 
2110*f9fbec18Smcpowers   if (mp_cmp_z(&f) == 0) {
2111*f9fbec18Smcpowers     res = MP_UNDEF;
2112*f9fbec18Smcpowers   } else
2113*f9fbec18Smcpowers   for (;;) {
2114*f9fbec18Smcpowers     int diff_sign;
2115*f9fbec18Smcpowers     while (mp_iseven(&f)) {
2116*f9fbec18Smcpowers       mp_size n = mp_trailing_zeros(&f);
2117*f9fbec18Smcpowers       if (!n) {
2118*f9fbec18Smcpowers 	res = MP_UNDEF;
2119*f9fbec18Smcpowers 	goto CLEANUP;
2120*f9fbec18Smcpowers       }
2121*f9fbec18Smcpowers       s_mp_div_2d(&f, n);
2122*f9fbec18Smcpowers       MP_CHECKOK( s_mp_mul_2d(&d, n) );
2123*f9fbec18Smcpowers       k += n;
2124*f9fbec18Smcpowers     }
2125*f9fbec18Smcpowers     if (mp_cmp_d(&f, 1) == MP_EQ) {	/* f == 1 */
2126*f9fbec18Smcpowers       res = k;
2127*f9fbec18Smcpowers       break;
2128*f9fbec18Smcpowers     }
2129*f9fbec18Smcpowers     diff_sign = mp_cmp(&f, &g);
2130*f9fbec18Smcpowers     if (diff_sign < 0) {		/* f < g */
2131*f9fbec18Smcpowers       s_mp_exch(&f, &g);
2132*f9fbec18Smcpowers       s_mp_exch(c, &d);
2133*f9fbec18Smcpowers     } else if (diff_sign == 0) {		/* f == g */
2134*f9fbec18Smcpowers       res = MP_UNDEF;		/* a and p are not relatively prime */
2135*f9fbec18Smcpowers       break;
2136*f9fbec18Smcpowers     }
2137*f9fbec18Smcpowers     if ((MP_DIGIT(&f,0) % 4) == (MP_DIGIT(&g,0) % 4)) {
2138*f9fbec18Smcpowers       MP_CHECKOK( mp_sub(&f, &g, &f) );	/* f = f - g */
2139*f9fbec18Smcpowers       MP_CHECKOK( mp_sub(c,  &d,  c) );	/* c = c - d */
2140*f9fbec18Smcpowers     } else {
2141*f9fbec18Smcpowers       MP_CHECKOK( mp_add(&f, &g, &f) );	/* f = f + g */
2142*f9fbec18Smcpowers       MP_CHECKOK( mp_add(c,  &d,  c) );	/* c = c + d */
2143*f9fbec18Smcpowers     }
2144*f9fbec18Smcpowers   }
2145*f9fbec18Smcpowers   if (res >= 0) {
2146*f9fbec18Smcpowers     while (MP_SIGN(c) != MP_ZPOS) {
2147*f9fbec18Smcpowers       MP_CHECKOK( mp_add(c, p, c) );
2148*f9fbec18Smcpowers     }
2149*f9fbec18Smcpowers     res = k;
2150*f9fbec18Smcpowers   }
2151*f9fbec18Smcpowers 
2152*f9fbec18Smcpowers CLEANUP:
2153*f9fbec18Smcpowers   mp_clear(&d);
2154*f9fbec18Smcpowers   mp_clear(&f);
2155*f9fbec18Smcpowers   mp_clear(&g);
2156*f9fbec18Smcpowers   return res;
2157*f9fbec18Smcpowers }
2158*f9fbec18Smcpowers 
2159*f9fbec18Smcpowers /* Compute T = (P ** -1) mod MP_RADIX.  Also works for 16-bit mp_digits.
2160*f9fbec18Smcpowers ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
2161*f9fbec18Smcpowers ** by Richard Schroeppel (a.k.a. Captain Nemo).
2162*f9fbec18Smcpowers */
2163*f9fbec18Smcpowers mp_digit  s_mp_invmod_radix(mp_digit P)
2164*f9fbec18Smcpowers {
2165*f9fbec18Smcpowers   mp_digit T = P;
2166*f9fbec18Smcpowers   T *= 2 - (P * T);
2167*f9fbec18Smcpowers   T *= 2 - (P * T);
2168*f9fbec18Smcpowers   T *= 2 - (P * T);
2169*f9fbec18Smcpowers   T *= 2 - (P * T);
2170*f9fbec18Smcpowers #if !defined(MP_USE_UINT_DIGIT)
2171*f9fbec18Smcpowers   T *= 2 - (P * T);
2172*f9fbec18Smcpowers   T *= 2 - (P * T);
2173*f9fbec18Smcpowers #endif
2174*f9fbec18Smcpowers   return T;
2175*f9fbec18Smcpowers }
2176*f9fbec18Smcpowers 
2177*f9fbec18Smcpowers /* Given c, k, and prime p, where a*c == 2**k (mod p),
2178*f9fbec18Smcpowers ** Compute x = (a ** -1) mod p.  This is similar to Montgomery reduction.
2179*f9fbec18Smcpowers ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
2180*f9fbec18Smcpowers ** by Richard Schroeppel (a.k.a. Captain Nemo).
2181*f9fbec18Smcpowers */
2182*f9fbec18Smcpowers mp_err  s_mp_fixup_reciprocal(const mp_int *c, const mp_int *p, int k, mp_int *x)
2183*f9fbec18Smcpowers {
2184*f9fbec18Smcpowers   int      k_orig = k;
2185*f9fbec18Smcpowers   mp_digit r;
2186*f9fbec18Smcpowers   mp_size  ix;
2187*f9fbec18Smcpowers   mp_err   res;
2188*f9fbec18Smcpowers 
2189*f9fbec18Smcpowers   if (mp_cmp_z(c) < 0) {		/* c < 0 */
2190*f9fbec18Smcpowers     MP_CHECKOK( mp_add(c, p, x) );	/* x = c + p */
2191*f9fbec18Smcpowers   } else {
2192*f9fbec18Smcpowers     MP_CHECKOK( mp_copy(c, x) );	/* x = c */
2193*f9fbec18Smcpowers   }
2194*f9fbec18Smcpowers 
2195*f9fbec18Smcpowers   /* make sure x is large enough */
2196*f9fbec18Smcpowers   ix = MP_HOWMANY(k, MP_DIGIT_BIT) + MP_USED(p) + 1;
2197*f9fbec18Smcpowers   ix = MP_MAX(ix, MP_USED(x));
2198*f9fbec18Smcpowers   MP_CHECKOK( s_mp_pad(x, ix) );
2199*f9fbec18Smcpowers 
2200*f9fbec18Smcpowers   r = 0 - s_mp_invmod_radix(MP_DIGIT(p,0));
2201*f9fbec18Smcpowers 
2202*f9fbec18Smcpowers   for (ix = 0; k > 0; ix++) {
2203*f9fbec18Smcpowers     int      j = MP_MIN(k, MP_DIGIT_BIT);
2204*f9fbec18Smcpowers     mp_digit v = r * MP_DIGIT(x, ix);
2205*f9fbec18Smcpowers     if (j < MP_DIGIT_BIT) {
2206*f9fbec18Smcpowers       v &= ((mp_digit)1 << j) - 1;	/* v = v mod (2 ** j) */
2207*f9fbec18Smcpowers     }
2208*f9fbec18Smcpowers     s_mp_mul_d_add_offset(p, v, x, ix); /* x += p * v * (RADIX ** ix) */
2209*f9fbec18Smcpowers     k -= j;
2210*f9fbec18Smcpowers   }
2211*f9fbec18Smcpowers   s_mp_clamp(x);
2212*f9fbec18Smcpowers   s_mp_div_2d(x, k_orig);
2213*f9fbec18Smcpowers   res = MP_OKAY;
2214*f9fbec18Smcpowers 
2215*f9fbec18Smcpowers CLEANUP:
2216*f9fbec18Smcpowers   return res;
2217*f9fbec18Smcpowers }
2218*f9fbec18Smcpowers 
2219*f9fbec18Smcpowers /* compute mod inverse using Schroeppel's method, only if m is odd */
2220*f9fbec18Smcpowers mp_err s_mp_invmod_odd_m(const mp_int *a, const mp_int *m, mp_int *c)
2221*f9fbec18Smcpowers {
2222*f9fbec18Smcpowers   int k;
2223*f9fbec18Smcpowers   mp_err  res;
2224*f9fbec18Smcpowers   mp_int  x;
2225*f9fbec18Smcpowers 
2226*f9fbec18Smcpowers   ARGCHK(a && m && c, MP_BADARG);
2227*f9fbec18Smcpowers 
2228*f9fbec18Smcpowers   if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
2229*f9fbec18Smcpowers     return MP_RANGE;
2230*f9fbec18Smcpowers   if (mp_iseven(m))
2231*f9fbec18Smcpowers     return MP_UNDEF;
2232*f9fbec18Smcpowers 
2233*f9fbec18Smcpowers   MP_DIGITS(&x) = 0;
2234*f9fbec18Smcpowers 
2235*f9fbec18Smcpowers   if (a == c) {
2236*f9fbec18Smcpowers     if ((res = mp_init_copy(&x, a)) != MP_OKAY)
2237*f9fbec18Smcpowers       return res;
2238*f9fbec18Smcpowers     if (a == m)
2239*f9fbec18Smcpowers       m = &x;
2240*f9fbec18Smcpowers     a = &x;
2241*f9fbec18Smcpowers   } else if (m == c) {
2242*f9fbec18Smcpowers     if ((res = mp_init_copy(&x, m)) != MP_OKAY)
2243*f9fbec18Smcpowers       return res;
2244*f9fbec18Smcpowers     m = &x;
2245*f9fbec18Smcpowers   } else {
2246*f9fbec18Smcpowers     MP_DIGITS(&x) = 0;
2247*f9fbec18Smcpowers   }
2248*f9fbec18Smcpowers 
2249*f9fbec18Smcpowers   MP_CHECKOK( s_mp_almost_inverse(a, m, c) );
2250*f9fbec18Smcpowers   k = res;
2251*f9fbec18Smcpowers   MP_CHECKOK( s_mp_fixup_reciprocal(c, m, k, c) );
2252*f9fbec18Smcpowers CLEANUP:
2253*f9fbec18Smcpowers   mp_clear(&x);
2254*f9fbec18Smcpowers   return res;
2255*f9fbec18Smcpowers }
2256*f9fbec18Smcpowers 
2257*f9fbec18Smcpowers /* Known good algorithm for computing modular inverse.  But slow. */
2258*f9fbec18Smcpowers mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c)
2259*f9fbec18Smcpowers {
2260*f9fbec18Smcpowers   mp_int  g, x;
2261*f9fbec18Smcpowers   mp_err  res;
2262*f9fbec18Smcpowers 
2263*f9fbec18Smcpowers   ARGCHK(a && m && c, MP_BADARG);
2264*f9fbec18Smcpowers 
2265*f9fbec18Smcpowers   if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
2266*f9fbec18Smcpowers     return MP_RANGE;
2267*f9fbec18Smcpowers 
2268*f9fbec18Smcpowers   MP_DIGITS(&g) = 0;
2269*f9fbec18Smcpowers   MP_DIGITS(&x) = 0;
2270*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&x, FLAG(a)) );
2271*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&g, FLAG(a)) );
2272*f9fbec18Smcpowers 
2273*f9fbec18Smcpowers   MP_CHECKOK( mp_xgcd(a, m, &g, &x, NULL) );
2274*f9fbec18Smcpowers 
2275*f9fbec18Smcpowers   if (mp_cmp_d(&g, 1) != MP_EQ) {
2276*f9fbec18Smcpowers     res = MP_UNDEF;
2277*f9fbec18Smcpowers     goto CLEANUP;
2278*f9fbec18Smcpowers   }
2279*f9fbec18Smcpowers 
2280*f9fbec18Smcpowers   res = mp_mod(&x, m, c);
2281*f9fbec18Smcpowers   SIGN(c) = SIGN(a);
2282*f9fbec18Smcpowers 
2283*f9fbec18Smcpowers CLEANUP:
2284*f9fbec18Smcpowers   mp_clear(&x);
2285*f9fbec18Smcpowers   mp_clear(&g);
2286*f9fbec18Smcpowers 
2287*f9fbec18Smcpowers   return res;
2288*f9fbec18Smcpowers }
2289*f9fbec18Smcpowers 
2290*f9fbec18Smcpowers /* modular inverse where modulus is 2**k. */
2291*f9fbec18Smcpowers /* c = a**-1 mod 2**k */
2292*f9fbec18Smcpowers mp_err s_mp_invmod_2d(const mp_int *a, mp_size k, mp_int *c)
2293*f9fbec18Smcpowers {
2294*f9fbec18Smcpowers   mp_err res;
2295*f9fbec18Smcpowers   mp_size ix = k + 4;
2296*f9fbec18Smcpowers   mp_int t0, t1, val, tmp, two2k;
2297*f9fbec18Smcpowers 
2298*f9fbec18Smcpowers   static const mp_digit d2 = 2;
2299*f9fbec18Smcpowers   static const mp_int two = { 0, MP_ZPOS, 1, 1, (mp_digit *)&d2 };
2300*f9fbec18Smcpowers 
2301*f9fbec18Smcpowers   if (mp_iseven(a))
2302*f9fbec18Smcpowers     return MP_UNDEF;
2303*f9fbec18Smcpowers   if (k <= MP_DIGIT_BIT) {
2304*f9fbec18Smcpowers     mp_digit i = s_mp_invmod_radix(MP_DIGIT(a,0));
2305*f9fbec18Smcpowers     if (k < MP_DIGIT_BIT)
2306*f9fbec18Smcpowers       i &= ((mp_digit)1 << k) - (mp_digit)1;
2307*f9fbec18Smcpowers     mp_set(c, i);
2308*f9fbec18Smcpowers     return MP_OKAY;
2309*f9fbec18Smcpowers   }
2310*f9fbec18Smcpowers   MP_DIGITS(&t0) = 0;
2311*f9fbec18Smcpowers   MP_DIGITS(&t1) = 0;
2312*f9fbec18Smcpowers   MP_DIGITS(&val) = 0;
2313*f9fbec18Smcpowers   MP_DIGITS(&tmp) = 0;
2314*f9fbec18Smcpowers   MP_DIGITS(&two2k) = 0;
2315*f9fbec18Smcpowers   MP_CHECKOK( mp_init_copy(&val, a) );
2316*f9fbec18Smcpowers   s_mp_mod_2d(&val, k);
2317*f9fbec18Smcpowers   MP_CHECKOK( mp_init_copy(&t0, &val) );
2318*f9fbec18Smcpowers   MP_CHECKOK( mp_init_copy(&t1, &t0)  );
2319*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&tmp, FLAG(a)) );
2320*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&two2k, FLAG(a)) );
2321*f9fbec18Smcpowers   MP_CHECKOK( s_mp_2expt(&two2k, k) );
2322*f9fbec18Smcpowers   do {
2323*f9fbec18Smcpowers     MP_CHECKOK( mp_mul(&val, &t1, &tmp)  );
2324*f9fbec18Smcpowers     MP_CHECKOK( mp_sub(&two, &tmp, &tmp) );
2325*f9fbec18Smcpowers     MP_CHECKOK( mp_mul(&t1, &tmp, &t1)   );
2326*f9fbec18Smcpowers     s_mp_mod_2d(&t1, k);
2327*f9fbec18Smcpowers     while (MP_SIGN(&t1) != MP_ZPOS) {
2328*f9fbec18Smcpowers       MP_CHECKOK( mp_add(&t1, &two2k, &t1) );
2329*f9fbec18Smcpowers     }
2330*f9fbec18Smcpowers     if (mp_cmp(&t1, &t0) == MP_EQ)
2331*f9fbec18Smcpowers       break;
2332*f9fbec18Smcpowers     MP_CHECKOK( mp_copy(&t1, &t0) );
2333*f9fbec18Smcpowers   } while (--ix > 0);
2334*f9fbec18Smcpowers   if (!ix) {
2335*f9fbec18Smcpowers     res = MP_UNDEF;
2336*f9fbec18Smcpowers   } else {
2337*f9fbec18Smcpowers     mp_exch(c, &t1);
2338*f9fbec18Smcpowers   }
2339*f9fbec18Smcpowers 
2340*f9fbec18Smcpowers CLEANUP:
2341*f9fbec18Smcpowers   mp_clear(&t0);
2342*f9fbec18Smcpowers   mp_clear(&t1);
2343*f9fbec18Smcpowers   mp_clear(&val);
2344*f9fbec18Smcpowers   mp_clear(&tmp);
2345*f9fbec18Smcpowers   mp_clear(&two2k);
2346*f9fbec18Smcpowers   return res;
2347*f9fbec18Smcpowers }
2348*f9fbec18Smcpowers 
2349*f9fbec18Smcpowers mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c)
2350*f9fbec18Smcpowers {
2351*f9fbec18Smcpowers   mp_err res;
2352*f9fbec18Smcpowers   mp_size k;
2353*f9fbec18Smcpowers   mp_int oddFactor, evenFactor;	/* factors of the modulus */
2354*f9fbec18Smcpowers   mp_int oddPart, evenPart;	/* parts to combine via CRT. */
2355*f9fbec18Smcpowers   mp_int C2, tmp1, tmp2;
2356*f9fbec18Smcpowers 
2357*f9fbec18Smcpowers   /*static const mp_digit d1 = 1; */
2358*f9fbec18Smcpowers   /*static const mp_int one = { MP_ZPOS, 1, 1, (mp_digit *)&d1 }; */
2359*f9fbec18Smcpowers 
2360*f9fbec18Smcpowers   if ((res = s_mp_ispow2(m)) >= 0) {
2361*f9fbec18Smcpowers     k = res;
2362*f9fbec18Smcpowers     return s_mp_invmod_2d(a, k, c);
2363*f9fbec18Smcpowers   }
2364*f9fbec18Smcpowers   MP_DIGITS(&oddFactor) = 0;
2365*f9fbec18Smcpowers   MP_DIGITS(&evenFactor) = 0;
2366*f9fbec18Smcpowers   MP_DIGITS(&oddPart) = 0;
2367*f9fbec18Smcpowers   MP_DIGITS(&evenPart) = 0;
2368*f9fbec18Smcpowers   MP_DIGITS(&C2)     = 0;
2369*f9fbec18Smcpowers   MP_DIGITS(&tmp1)   = 0;
2370*f9fbec18Smcpowers   MP_DIGITS(&tmp2)   = 0;
2371*f9fbec18Smcpowers 
2372*f9fbec18Smcpowers   MP_CHECKOK( mp_init_copy(&oddFactor, m) );    /* oddFactor = m */
2373*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&evenFactor, FLAG(m)) );
2374*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&oddPart, FLAG(m)) );
2375*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&evenPart, FLAG(m)) );
2376*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&C2, FLAG(m))     );
2377*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&tmp1, FLAG(m))   );
2378*f9fbec18Smcpowers   MP_CHECKOK( mp_init(&tmp2, FLAG(m))   );
2379*f9fbec18Smcpowers 
2380*f9fbec18Smcpowers   k = mp_trailing_zeros(m);
2381*f9fbec18Smcpowers   s_mp_div_2d(&oddFactor, k);
2382*f9fbec18Smcpowers   MP_CHECKOK( s_mp_2expt(&evenFactor, k) );
2383*f9fbec18Smcpowers 
2384*f9fbec18Smcpowers   /* compute a**-1 mod oddFactor. */
2385*f9fbec18Smcpowers   MP_CHECKOK( s_mp_invmod_odd_m(a, &oddFactor, &oddPart) );
2386*f9fbec18Smcpowers   /* compute a**-1 mod evenFactor, where evenFactor == 2**k. */
2387*f9fbec18Smcpowers   MP_CHECKOK( s_mp_invmod_2d(   a,       k,    &evenPart) );
2388*f9fbec18Smcpowers 
2389*f9fbec18Smcpowers   /* Use Chinese Remainer theorem to compute a**-1 mod m. */
2390*f9fbec18Smcpowers   /* let m1 = oddFactor,  v1 = oddPart,
2391*f9fbec18Smcpowers    * let m2 = evenFactor, v2 = evenPart.
2392*f9fbec18Smcpowers    */
2393*f9fbec18Smcpowers 
2394*f9fbec18Smcpowers   /* Compute C2 = m1**-1 mod m2. */
2395*f9fbec18Smcpowers   MP_CHECKOK( s_mp_invmod_2d(&oddFactor, k,    &C2) );
2396*f9fbec18Smcpowers 
2397*f9fbec18Smcpowers   /* compute u = (v2 - v1)*C2 mod m2 */
2398*f9fbec18Smcpowers   MP_CHECKOK( mp_sub(&evenPart, &oddPart,   &tmp1) );
2399*f9fbec18Smcpowers   MP_CHECKOK( mp_mul(&tmp1,     &C2,        &tmp2) );
2400*f9fbec18Smcpowers   s_mp_mod_2d(&tmp2, k);
2401*f9fbec18Smcpowers   while (MP_SIGN(&tmp2) != MP_ZPOS) {
2402*f9fbec18Smcpowers     MP_CHECKOK( mp_add(&tmp2, &evenFactor, &tmp2) );
2403*f9fbec18Smcpowers   }
2404*f9fbec18Smcpowers 
2405*f9fbec18Smcpowers   /* compute answer = v1 + u*m1 */
2406*f9fbec18Smcpowers   MP_CHECKOK( mp_mul(&tmp2,     &oddFactor, c) );
2407*f9fbec18Smcpowers   MP_CHECKOK( mp_add(&oddPart,  c,          c) );
2408*f9fbec18Smcpowers   /* not sure this is necessary, but it's low cost if not. */
2409*f9fbec18Smcpowers   MP_CHECKOK( mp_mod(c,         m,          c) );
2410*f9fbec18Smcpowers 
2411*f9fbec18Smcpowers CLEANUP:
2412*f9fbec18Smcpowers   mp_clear(&oddFactor);
2413*f9fbec18Smcpowers   mp_clear(&evenFactor);
2414*f9fbec18Smcpowers   mp_clear(&oddPart);
2415*f9fbec18Smcpowers   mp_clear(&evenPart);
2416*f9fbec18Smcpowers   mp_clear(&C2);
2417*f9fbec18Smcpowers   mp_clear(&tmp1);
2418*f9fbec18Smcpowers   mp_clear(&tmp2);
2419*f9fbec18Smcpowers   return res;
2420*f9fbec18Smcpowers }
2421*f9fbec18Smcpowers 
2422*f9fbec18Smcpowers 
2423*f9fbec18Smcpowers /* {{{ mp_invmod(a, m, c) */
2424*f9fbec18Smcpowers 
2425*f9fbec18Smcpowers /*
2426*f9fbec18Smcpowers   mp_invmod(a, m, c)
2427*f9fbec18Smcpowers 
2428*f9fbec18Smcpowers   Compute c = a^-1 (mod m), if there is an inverse for a (mod m).
2429*f9fbec18Smcpowers   This is equivalent to the question of whether (a, m) = 1.  If not,
2430*f9fbec18Smcpowers   MP_UNDEF is returned, and there is no inverse.
2431*f9fbec18Smcpowers  */
2432*f9fbec18Smcpowers 
2433*f9fbec18Smcpowers mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
2434*f9fbec18Smcpowers {
2435*f9fbec18Smcpowers 
2436*f9fbec18Smcpowers   ARGCHK(a && m && c, MP_BADARG);
2437*f9fbec18Smcpowers 
2438*f9fbec18Smcpowers   if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
2439*f9fbec18Smcpowers     return MP_RANGE;
2440*f9fbec18Smcpowers 
2441*f9fbec18Smcpowers   if (mp_isodd(m)) {
2442*f9fbec18Smcpowers     return s_mp_invmod_odd_m(a, m, c);
2443*f9fbec18Smcpowers   }
2444*f9fbec18Smcpowers   if (mp_iseven(a))
2445*f9fbec18Smcpowers     return MP_UNDEF;	/* not invertable */
2446*f9fbec18Smcpowers 
2447*f9fbec18Smcpowers   return s_mp_invmod_even_m(a, m, c);
2448*f9fbec18Smcpowers 
2449*f9fbec18Smcpowers } /* end mp_invmod() */
2450*f9fbec18Smcpowers 
2451*f9fbec18Smcpowers /* }}} */
2452*f9fbec18Smcpowers #endif /* if MP_NUMTH */
2453*f9fbec18Smcpowers 
2454*f9fbec18Smcpowers /* }}} */
2455*f9fbec18Smcpowers 
2456*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
2457*f9fbec18Smcpowers /* {{{ mp_print(mp, ofp) */
2458*f9fbec18Smcpowers 
2459*f9fbec18Smcpowers #if MP_IOFUNC
2460*f9fbec18Smcpowers /*
2461*f9fbec18Smcpowers   mp_print(mp, ofp)
2462*f9fbec18Smcpowers 
2463*f9fbec18Smcpowers   Print a textual representation of the given mp_int on the output
2464*f9fbec18Smcpowers   stream 'ofp'.  Output is generated using the internal radix.
2465*f9fbec18Smcpowers  */
2466*f9fbec18Smcpowers 
2467*f9fbec18Smcpowers void   mp_print(mp_int *mp, FILE *ofp)
2468*f9fbec18Smcpowers {
2469*f9fbec18Smcpowers   int   ix;
2470*f9fbec18Smcpowers 
2471*f9fbec18Smcpowers   if(mp == NULL || ofp == NULL)
2472*f9fbec18Smcpowers     return;
2473*f9fbec18Smcpowers 
2474*f9fbec18Smcpowers   fputc((SIGN(mp) == NEG) ? '-' : '+', ofp);
2475*f9fbec18Smcpowers 
2476*f9fbec18Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
2477*f9fbec18Smcpowers     fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix));
2478*f9fbec18Smcpowers   }
2479*f9fbec18Smcpowers 
2480*f9fbec18Smcpowers } /* end mp_print() */
2481*f9fbec18Smcpowers 
2482*f9fbec18Smcpowers #endif /* if MP_IOFUNC */
2483*f9fbec18Smcpowers 
2484*f9fbec18Smcpowers /* }}} */
2485*f9fbec18Smcpowers 
2486*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
2487*f9fbec18Smcpowers /* {{{ More I/O Functions */
2488*f9fbec18Smcpowers 
2489*f9fbec18Smcpowers /* {{{ mp_read_raw(mp, str, len) */
2490*f9fbec18Smcpowers 
2491*f9fbec18Smcpowers /*
2492*f9fbec18Smcpowers    mp_read_raw(mp, str, len)
2493*f9fbec18Smcpowers 
2494*f9fbec18Smcpowers    Read in a raw value (base 256) into the given mp_int
2495*f9fbec18Smcpowers  */
2496*f9fbec18Smcpowers 
2497*f9fbec18Smcpowers mp_err  mp_read_raw(mp_int *mp, char *str, int len)
2498*f9fbec18Smcpowers {
2499*f9fbec18Smcpowers   int            ix;
2500*f9fbec18Smcpowers   mp_err         res;
2501*f9fbec18Smcpowers   unsigned char *ustr = (unsigned char *)str;
2502*f9fbec18Smcpowers 
2503*f9fbec18Smcpowers   ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
2504*f9fbec18Smcpowers 
2505*f9fbec18Smcpowers   mp_zero(mp);
2506*f9fbec18Smcpowers 
2507*f9fbec18Smcpowers   /* Get sign from first byte */
2508*f9fbec18Smcpowers   if(ustr[0])
2509*f9fbec18Smcpowers     SIGN(mp) = NEG;
2510*f9fbec18Smcpowers   else
2511*f9fbec18Smcpowers     SIGN(mp) = ZPOS;
2512*f9fbec18Smcpowers 
2513*f9fbec18Smcpowers   /* Read the rest of the digits */
2514*f9fbec18Smcpowers   for(ix = 1; ix < len; ix++) {
2515*f9fbec18Smcpowers     if((res = mp_mul_d(mp, 256, mp)) != MP_OKAY)
2516*f9fbec18Smcpowers       return res;
2517*f9fbec18Smcpowers     if((res = mp_add_d(mp, ustr[ix], mp)) != MP_OKAY)
2518*f9fbec18Smcpowers       return res;
2519*f9fbec18Smcpowers   }
2520*f9fbec18Smcpowers 
2521*f9fbec18Smcpowers   return MP_OKAY;
2522*f9fbec18Smcpowers 
2523*f9fbec18Smcpowers } /* end mp_read_raw() */
2524*f9fbec18Smcpowers 
2525*f9fbec18Smcpowers /* }}} */
2526*f9fbec18Smcpowers 
2527*f9fbec18Smcpowers /* {{{ mp_raw_size(mp) */
2528*f9fbec18Smcpowers 
2529*f9fbec18Smcpowers int    mp_raw_size(mp_int *mp)
2530*f9fbec18Smcpowers {
2531*f9fbec18Smcpowers   ARGCHK(mp != NULL, 0);
2532*f9fbec18Smcpowers 
2533*f9fbec18Smcpowers   return (USED(mp) * sizeof(mp_digit)) + 1;
2534*f9fbec18Smcpowers 
2535*f9fbec18Smcpowers } /* end mp_raw_size() */
2536*f9fbec18Smcpowers 
2537*f9fbec18Smcpowers /* }}} */
2538*f9fbec18Smcpowers 
2539*f9fbec18Smcpowers /* {{{ mp_toraw(mp, str) */
2540*f9fbec18Smcpowers 
2541*f9fbec18Smcpowers mp_err mp_toraw(mp_int *mp, char *str)
2542*f9fbec18Smcpowers {
2543*f9fbec18Smcpowers   int  ix, jx, pos = 1;
2544*f9fbec18Smcpowers 
2545*f9fbec18Smcpowers   ARGCHK(mp != NULL && str != NULL, MP_BADARG);
2546*f9fbec18Smcpowers 
2547*f9fbec18Smcpowers   str[0] = (char)SIGN(mp);
2548*f9fbec18Smcpowers 
2549*f9fbec18Smcpowers   /* Iterate over each digit... */
2550*f9fbec18Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
2551*f9fbec18Smcpowers     mp_digit  d = DIGIT(mp, ix);
2552*f9fbec18Smcpowers 
2553*f9fbec18Smcpowers     /* Unpack digit bytes, high order first */
2554*f9fbec18Smcpowers     for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
2555*f9fbec18Smcpowers       str[pos++] = (char)(d >> (jx * CHAR_BIT));
2556*f9fbec18Smcpowers     }
2557*f9fbec18Smcpowers   }
2558*f9fbec18Smcpowers 
2559*f9fbec18Smcpowers   return MP_OKAY;
2560*f9fbec18Smcpowers 
2561*f9fbec18Smcpowers } /* end mp_toraw() */
2562*f9fbec18Smcpowers 
2563*f9fbec18Smcpowers /* }}} */
2564*f9fbec18Smcpowers 
2565*f9fbec18Smcpowers /* {{{ mp_read_radix(mp, str, radix) */
2566*f9fbec18Smcpowers 
2567*f9fbec18Smcpowers /*
2568*f9fbec18Smcpowers   mp_read_radix(mp, str, radix)
2569*f9fbec18Smcpowers 
2570*f9fbec18Smcpowers   Read an integer from the given string, and set mp to the resulting
2571*f9fbec18Smcpowers   value.  The input is presumed to be in base 10.  Leading non-digit
2572*f9fbec18Smcpowers   characters are ignored, and the function reads until a non-digit
2573*f9fbec18Smcpowers   character or the end of the string.
2574*f9fbec18Smcpowers  */
2575*f9fbec18Smcpowers 
2576*f9fbec18Smcpowers mp_err  mp_read_radix(mp_int *mp, const char *str, int radix)
2577*f9fbec18Smcpowers {
2578*f9fbec18Smcpowers   int     ix = 0, val = 0;
2579*f9fbec18Smcpowers   mp_err  res;
2580*f9fbec18Smcpowers   mp_sign sig = ZPOS;
2581*f9fbec18Smcpowers 
2582*f9fbec18Smcpowers   ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX,
2583*f9fbec18Smcpowers 	 MP_BADARG);
2584*f9fbec18Smcpowers 
2585*f9fbec18Smcpowers   mp_zero(mp);
2586*f9fbec18Smcpowers 
2587*f9fbec18Smcpowers   /* Skip leading non-digit characters until a digit or '-' or '+' */
2588*f9fbec18Smcpowers   while(str[ix] &&
2589*f9fbec18Smcpowers 	(s_mp_tovalue(str[ix], radix) < 0) &&
2590*f9fbec18Smcpowers 	str[ix] != '-' &&
2591*f9fbec18Smcpowers 	str[ix] != '+') {
2592*f9fbec18Smcpowers     ++ix;
2593*f9fbec18Smcpowers   }
2594*f9fbec18Smcpowers 
2595*f9fbec18Smcpowers   if(str[ix] == '-') {
2596*f9fbec18Smcpowers     sig = NEG;
2597*f9fbec18Smcpowers     ++ix;
2598*f9fbec18Smcpowers   } else if(str[ix] == '+') {
2599*f9fbec18Smcpowers     sig = ZPOS; /* this is the default anyway... */
2600*f9fbec18Smcpowers     ++ix;
2601*f9fbec18Smcpowers   }
2602*f9fbec18Smcpowers 
2603*f9fbec18Smcpowers   while((val = s_mp_tovalue(str[ix], radix)) >= 0) {
2604*f9fbec18Smcpowers     if((res = s_mp_mul_d(mp, radix)) != MP_OKAY)
2605*f9fbec18Smcpowers       return res;
2606*f9fbec18Smcpowers     if((res = s_mp_add_d(mp, val)) != MP_OKAY)
2607*f9fbec18Smcpowers       return res;
2608*f9fbec18Smcpowers     ++ix;
2609*f9fbec18Smcpowers   }
2610*f9fbec18Smcpowers 
2611*f9fbec18Smcpowers   if(s_mp_cmp_d(mp, 0) == MP_EQ)
2612*f9fbec18Smcpowers     SIGN(mp) = ZPOS;
2613*f9fbec18Smcpowers   else
2614*f9fbec18Smcpowers     SIGN(mp) = sig;
2615*f9fbec18Smcpowers 
2616*f9fbec18Smcpowers   return MP_OKAY;
2617*f9fbec18Smcpowers 
2618*f9fbec18Smcpowers } /* end mp_read_radix() */
2619*f9fbec18Smcpowers 
2620*f9fbec18Smcpowers mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix)
2621*f9fbec18Smcpowers {
2622*f9fbec18Smcpowers   int     radix = default_radix;
2623*f9fbec18Smcpowers   int     cx;
2624*f9fbec18Smcpowers   mp_sign sig   = ZPOS;
2625*f9fbec18Smcpowers   mp_err  res;
2626*f9fbec18Smcpowers 
2627*f9fbec18Smcpowers   /* Skip leading non-digit characters until a digit or '-' or '+' */
2628*f9fbec18Smcpowers   while ((cx = *str) != 0 &&
2629*f9fbec18Smcpowers 	(s_mp_tovalue(cx, radix) < 0) &&
2630*f9fbec18Smcpowers 	cx != '-' &&
2631*f9fbec18Smcpowers 	cx != '+') {
2632*f9fbec18Smcpowers     ++str;
2633*f9fbec18Smcpowers   }
2634*f9fbec18Smcpowers 
2635*f9fbec18Smcpowers   if (cx == '-') {
2636*f9fbec18Smcpowers     sig = NEG;
2637*f9fbec18Smcpowers     ++str;
2638*f9fbec18Smcpowers   } else if (cx == '+') {
2639*f9fbec18Smcpowers     sig = ZPOS; /* this is the default anyway... */
2640*f9fbec18Smcpowers     ++str;
2641*f9fbec18Smcpowers   }
2642*f9fbec18Smcpowers 
2643*f9fbec18Smcpowers   if (str[0] == '0') {
2644*f9fbec18Smcpowers     if ((str[1] | 0x20) == 'x') {
2645*f9fbec18Smcpowers       radix = 16;
2646*f9fbec18Smcpowers       str += 2;
2647*f9fbec18Smcpowers     } else {
2648*f9fbec18Smcpowers       radix = 8;
2649*f9fbec18Smcpowers       str++;
2650*f9fbec18Smcpowers     }
2651*f9fbec18Smcpowers   }
2652*f9fbec18Smcpowers   res = mp_read_radix(a, str, radix);
2653*f9fbec18Smcpowers   if (res == MP_OKAY) {
2654*f9fbec18Smcpowers     MP_SIGN(a) = (s_mp_cmp_d(a, 0) == MP_EQ) ? ZPOS : sig;
2655*f9fbec18Smcpowers   }
2656*f9fbec18Smcpowers   return res;
2657*f9fbec18Smcpowers }
2658*f9fbec18Smcpowers 
2659*f9fbec18Smcpowers /* }}} */
2660*f9fbec18Smcpowers 
2661*f9fbec18Smcpowers /* {{{ mp_radix_size(mp, radix) */
2662*f9fbec18Smcpowers 
2663*f9fbec18Smcpowers int    mp_radix_size(mp_int *mp, int radix)
2664*f9fbec18Smcpowers {
2665*f9fbec18Smcpowers   int  bits;
2666*f9fbec18Smcpowers 
2667*f9fbec18Smcpowers   if(!mp || radix < 2 || radix > MAX_RADIX)
2668*f9fbec18Smcpowers     return 0;
2669*f9fbec18Smcpowers 
2670*f9fbec18Smcpowers   bits = USED(mp) * DIGIT_BIT - 1;
2671*f9fbec18Smcpowers 
2672*f9fbec18Smcpowers   return s_mp_outlen(bits, radix);
2673*f9fbec18Smcpowers 
2674*f9fbec18Smcpowers } /* end mp_radix_size() */
2675*f9fbec18Smcpowers 
2676*f9fbec18Smcpowers /* }}} */
2677*f9fbec18Smcpowers 
2678*f9fbec18Smcpowers /* {{{ mp_toradix(mp, str, radix) */
2679*f9fbec18Smcpowers 
2680*f9fbec18Smcpowers mp_err mp_toradix(mp_int *mp, char *str, int radix)
2681*f9fbec18Smcpowers {
2682*f9fbec18Smcpowers   int  ix, pos = 0;
2683*f9fbec18Smcpowers 
2684*f9fbec18Smcpowers   ARGCHK(mp != NULL && str != NULL, MP_BADARG);
2685*f9fbec18Smcpowers   ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE);
2686*f9fbec18Smcpowers 
2687*f9fbec18Smcpowers   if(mp_cmp_z(mp) == MP_EQ) {
2688*f9fbec18Smcpowers     str[0] = '0';
2689*f9fbec18Smcpowers     str[1] = '\0';
2690*f9fbec18Smcpowers   } else {
2691*f9fbec18Smcpowers     mp_err   res;
2692*f9fbec18Smcpowers     mp_int   tmp;
2693*f9fbec18Smcpowers     mp_sign  sgn;
2694*f9fbec18Smcpowers     mp_digit rem, rdx = (mp_digit)radix;
2695*f9fbec18Smcpowers     char     ch;
2696*f9fbec18Smcpowers 
2697*f9fbec18Smcpowers     if((res = mp_init_copy(&tmp, mp)) != MP_OKAY)
2698*f9fbec18Smcpowers       return res;
2699*f9fbec18Smcpowers 
2700*f9fbec18Smcpowers     /* Save sign for later, and take absolute value */
2701*f9fbec18Smcpowers     sgn = SIGN(&tmp); SIGN(&tmp) = ZPOS;
2702*f9fbec18Smcpowers 
2703*f9fbec18Smcpowers     /* Generate output digits in reverse order      */
2704*f9fbec18Smcpowers     while(mp_cmp_z(&tmp) != 0) {
2705*f9fbec18Smcpowers       if((res = mp_div_d(&tmp, rdx, &tmp, &rem)) != MP_OKAY) {
2706*f9fbec18Smcpowers 	mp_clear(&tmp);
2707*f9fbec18Smcpowers 	return res;
2708*f9fbec18Smcpowers       }
2709*f9fbec18Smcpowers 
2710*f9fbec18Smcpowers       /* Generate digits, use capital letters */
2711*f9fbec18Smcpowers       ch = s_mp_todigit(rem, radix, 0);
2712*f9fbec18Smcpowers 
2713*f9fbec18Smcpowers       str[pos++] = ch;
2714*f9fbec18Smcpowers     }
2715*f9fbec18Smcpowers 
2716*f9fbec18Smcpowers     /* Add - sign if original value was negative */
2717*f9fbec18Smcpowers     if(sgn == NEG)
2718*f9fbec18Smcpowers       str[pos++] = '-';
2719*f9fbec18Smcpowers 
2720*f9fbec18Smcpowers     /* Add trailing NUL to end the string        */
2721*f9fbec18Smcpowers     str[pos--] = '\0';
2722*f9fbec18Smcpowers 
2723*f9fbec18Smcpowers     /* Reverse the digits and sign indicator     */
2724*f9fbec18Smcpowers     ix = 0;
2725*f9fbec18Smcpowers     while(ix < pos) {
2726*f9fbec18Smcpowers       char tmp = str[ix];
2727*f9fbec18Smcpowers 
2728*f9fbec18Smcpowers       str[ix] = str[pos];
2729*f9fbec18Smcpowers       str[pos] = tmp;
2730*f9fbec18Smcpowers       ++ix;
2731*f9fbec18Smcpowers       --pos;
2732*f9fbec18Smcpowers     }
2733*f9fbec18Smcpowers 
2734*f9fbec18Smcpowers     mp_clear(&tmp);
2735*f9fbec18Smcpowers   }
2736*f9fbec18Smcpowers 
2737*f9fbec18Smcpowers   return MP_OKAY;
2738*f9fbec18Smcpowers 
2739*f9fbec18Smcpowers } /* end mp_toradix() */
2740*f9fbec18Smcpowers 
2741*f9fbec18Smcpowers /* }}} */
2742*f9fbec18Smcpowers 
2743*f9fbec18Smcpowers /* {{{ mp_tovalue(ch, r) */
2744*f9fbec18Smcpowers 
2745*f9fbec18Smcpowers int    mp_tovalue(char ch, int r)
2746*f9fbec18Smcpowers {
2747*f9fbec18Smcpowers   return s_mp_tovalue(ch, r);
2748*f9fbec18Smcpowers 
2749*f9fbec18Smcpowers } /* end mp_tovalue() */
2750*f9fbec18Smcpowers 
2751*f9fbec18Smcpowers /* }}} */
2752*f9fbec18Smcpowers 
2753*f9fbec18Smcpowers /* }}} */
2754*f9fbec18Smcpowers 
2755*f9fbec18Smcpowers /* {{{ mp_strerror(ec) */
2756*f9fbec18Smcpowers 
2757*f9fbec18Smcpowers /*
2758*f9fbec18Smcpowers   mp_strerror(ec)
2759*f9fbec18Smcpowers 
2760*f9fbec18Smcpowers   Return a string describing the meaning of error code 'ec'.  The
2761*f9fbec18Smcpowers   string returned is allocated in static memory, so the caller should
2762*f9fbec18Smcpowers   not attempt to modify or free the memory associated with this
2763*f9fbec18Smcpowers   string.
2764*f9fbec18Smcpowers  */
2765*f9fbec18Smcpowers const char  *mp_strerror(mp_err ec)
2766*f9fbec18Smcpowers {
2767*f9fbec18Smcpowers   int   aec = (ec < 0) ? -ec : ec;
2768*f9fbec18Smcpowers 
2769*f9fbec18Smcpowers   /* Code values are negative, so the senses of these comparisons
2770*f9fbec18Smcpowers      are accurate */
2771*f9fbec18Smcpowers   if(ec < MP_LAST_CODE || ec > MP_OKAY) {
2772*f9fbec18Smcpowers     return mp_err_string[0];  /* unknown error code */
2773*f9fbec18Smcpowers   } else {
2774*f9fbec18Smcpowers     return mp_err_string[aec + 1];
2775*f9fbec18Smcpowers   }
2776*f9fbec18Smcpowers 
2777*f9fbec18Smcpowers } /* end mp_strerror() */
2778*f9fbec18Smcpowers 
2779*f9fbec18Smcpowers /* }}} */
2780*f9fbec18Smcpowers 
2781*f9fbec18Smcpowers /*========================================================================*/
2782*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
2783*f9fbec18Smcpowers /* Static function definitions (internal use only)                        */
2784*f9fbec18Smcpowers 
2785*f9fbec18Smcpowers /* {{{ Memory management */
2786*f9fbec18Smcpowers 
2787*f9fbec18Smcpowers /* {{{ s_mp_grow(mp, min) */
2788*f9fbec18Smcpowers 
2789*f9fbec18Smcpowers /* Make sure there are at least 'min' digits allocated to mp              */
2790*f9fbec18Smcpowers mp_err   s_mp_grow(mp_int *mp, mp_size min)
2791*f9fbec18Smcpowers {
2792*f9fbec18Smcpowers   if(min > ALLOC(mp)) {
2793*f9fbec18Smcpowers     mp_digit   *tmp;
2794*f9fbec18Smcpowers 
2795*f9fbec18Smcpowers     /* Set min to next nearest default precision block size */
2796*f9fbec18Smcpowers     min = MP_ROUNDUP(min, s_mp_defprec);
2797*f9fbec18Smcpowers 
2798*f9fbec18Smcpowers     if((tmp = s_mp_alloc(min, sizeof(mp_digit), FLAG(mp))) == NULL)
2799*f9fbec18Smcpowers       return MP_MEM;
2800*f9fbec18Smcpowers 
2801*f9fbec18Smcpowers     s_mp_copy(DIGITS(mp), tmp, USED(mp));
2802*f9fbec18Smcpowers 
2803*f9fbec18Smcpowers #if MP_CRYPTO
2804*f9fbec18Smcpowers     s_mp_setz(DIGITS(mp), ALLOC(mp));
2805*f9fbec18Smcpowers #endif
2806*f9fbec18Smcpowers     s_mp_free(DIGITS(mp), ALLOC(mp));
2807*f9fbec18Smcpowers     DIGITS(mp) = tmp;
2808*f9fbec18Smcpowers     ALLOC(mp) = min;
2809*f9fbec18Smcpowers   }
2810*f9fbec18Smcpowers 
2811*f9fbec18Smcpowers   return MP_OKAY;
2812*f9fbec18Smcpowers 
2813*f9fbec18Smcpowers } /* end s_mp_grow() */
2814*f9fbec18Smcpowers 
2815*f9fbec18Smcpowers /* }}} */
2816*f9fbec18Smcpowers 
2817*f9fbec18Smcpowers /* {{{ s_mp_pad(mp, min) */
2818*f9fbec18Smcpowers 
2819*f9fbec18Smcpowers /* Make sure the used size of mp is at least 'min', growing if needed     */
2820*f9fbec18Smcpowers mp_err   s_mp_pad(mp_int *mp, mp_size min)
2821*f9fbec18Smcpowers {
2822*f9fbec18Smcpowers   if(min > USED(mp)) {
2823*f9fbec18Smcpowers     mp_err  res;
2824*f9fbec18Smcpowers 
2825*f9fbec18Smcpowers     /* Make sure there is room to increase precision  */
2826*f9fbec18Smcpowers     if (min > ALLOC(mp)) {
2827*f9fbec18Smcpowers       if ((res = s_mp_grow(mp, min)) != MP_OKAY)
2828*f9fbec18Smcpowers 	return res;
2829*f9fbec18Smcpowers     } else {
2830*f9fbec18Smcpowers       s_mp_setz(DIGITS(mp) + USED(mp), min - USED(mp));
2831*f9fbec18Smcpowers     }
2832*f9fbec18Smcpowers 
2833*f9fbec18Smcpowers     /* Increase precision; should already be 0-filled */
2834*f9fbec18Smcpowers     USED(mp) = min;
2835*f9fbec18Smcpowers   }
2836*f9fbec18Smcpowers 
2837*f9fbec18Smcpowers   return MP_OKAY;
2838*f9fbec18Smcpowers 
2839*f9fbec18Smcpowers } /* end s_mp_pad() */
2840*f9fbec18Smcpowers 
2841*f9fbec18Smcpowers /* }}} */
2842*f9fbec18Smcpowers 
2843*f9fbec18Smcpowers /* {{{ s_mp_setz(dp, count) */
2844*f9fbec18Smcpowers 
2845*f9fbec18Smcpowers #if MP_MACRO == 0
2846*f9fbec18Smcpowers /* Set 'count' digits pointed to by dp to be zeroes                       */
2847*f9fbec18Smcpowers void s_mp_setz(mp_digit *dp, mp_size count)
2848*f9fbec18Smcpowers {
2849*f9fbec18Smcpowers #if MP_MEMSET == 0
2850*f9fbec18Smcpowers   int  ix;
2851*f9fbec18Smcpowers 
2852*f9fbec18Smcpowers   for(ix = 0; ix < count; ix++)
2853*f9fbec18Smcpowers     dp[ix] = 0;
2854*f9fbec18Smcpowers #else
2855*f9fbec18Smcpowers   memset(dp, 0, count * sizeof(mp_digit));
2856*f9fbec18Smcpowers #endif
2857*f9fbec18Smcpowers 
2858*f9fbec18Smcpowers } /* end s_mp_setz() */
2859*f9fbec18Smcpowers #endif
2860*f9fbec18Smcpowers 
2861*f9fbec18Smcpowers /* }}} */
2862*f9fbec18Smcpowers 
2863*f9fbec18Smcpowers /* {{{ s_mp_copy(sp, dp, count) */
2864*f9fbec18Smcpowers 
2865*f9fbec18Smcpowers #if MP_MACRO == 0
2866*f9fbec18Smcpowers /* Copy 'count' digits from sp to dp                                      */
2867*f9fbec18Smcpowers void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count)
2868*f9fbec18Smcpowers {
2869*f9fbec18Smcpowers #if MP_MEMCPY == 0
2870*f9fbec18Smcpowers   int  ix;
2871*f9fbec18Smcpowers 
2872*f9fbec18Smcpowers   for(ix = 0; ix < count; ix++)
2873*f9fbec18Smcpowers     dp[ix] = sp[ix];
2874*f9fbec18Smcpowers #else
2875*f9fbec18Smcpowers   memcpy(dp, sp, count * sizeof(mp_digit));
2876*f9fbec18Smcpowers #endif
2877*f9fbec18Smcpowers 
2878*f9fbec18Smcpowers } /* end s_mp_copy() */
2879*f9fbec18Smcpowers #endif
2880*f9fbec18Smcpowers 
2881*f9fbec18Smcpowers /* }}} */
2882*f9fbec18Smcpowers 
2883*f9fbec18Smcpowers /* {{{ s_mp_alloc(nb, ni, kmflag) */
2884*f9fbec18Smcpowers 
2885*f9fbec18Smcpowers #if MP_MACRO == 0
2886*f9fbec18Smcpowers /* Allocate ni records of nb bytes each, and return a pointer to that     */
2887*f9fbec18Smcpowers void    *s_mp_alloc(size_t nb, size_t ni, int kmflag)
2888*f9fbec18Smcpowers {
2889*f9fbec18Smcpowers   mp_int *mp;
2890*f9fbec18Smcpowers   ++mp_allocs;
2891*f9fbec18Smcpowers #ifdef _KERNEL
2892*f9fbec18Smcpowers   mp = kmem_zalloc(nb * ni, kmflag);
2893*f9fbec18Smcpowers   if (mp != NULL)
2894*f9fbec18Smcpowers     FLAG(mp) = kmflag;
2895*f9fbec18Smcpowers   return (mp);
2896*f9fbec18Smcpowers #else
2897*f9fbec18Smcpowers   return calloc(nb, ni);
2898*f9fbec18Smcpowers #endif
2899*f9fbec18Smcpowers 
2900*f9fbec18Smcpowers } /* end s_mp_alloc() */
2901*f9fbec18Smcpowers #endif
2902*f9fbec18Smcpowers 
2903*f9fbec18Smcpowers /* }}} */
2904*f9fbec18Smcpowers 
2905*f9fbec18Smcpowers /* {{{ s_mp_free(ptr) */
2906*f9fbec18Smcpowers 
2907*f9fbec18Smcpowers #if MP_MACRO == 0
2908*f9fbec18Smcpowers /* Free the memory pointed to by ptr                                      */
2909*f9fbec18Smcpowers void     s_mp_free(void *ptr, mp_size alloc)
2910*f9fbec18Smcpowers {
2911*f9fbec18Smcpowers   if(ptr) {
2912*f9fbec18Smcpowers     ++mp_frees;
2913*f9fbec18Smcpowers #ifdef _KERNEL
2914*f9fbec18Smcpowers     kmem_free(ptr, alloc * sizeof (mp_digit));
2915*f9fbec18Smcpowers #else
2916*f9fbec18Smcpowers     free(ptr);
2917*f9fbec18Smcpowers #endif
2918*f9fbec18Smcpowers   }
2919*f9fbec18Smcpowers } /* end s_mp_free() */
2920*f9fbec18Smcpowers #endif
2921*f9fbec18Smcpowers 
2922*f9fbec18Smcpowers /* }}} */
2923*f9fbec18Smcpowers 
2924*f9fbec18Smcpowers /* {{{ s_mp_clamp(mp) */
2925*f9fbec18Smcpowers 
2926*f9fbec18Smcpowers #if MP_MACRO == 0
2927*f9fbec18Smcpowers /* Remove leading zeroes from the given value                             */
2928*f9fbec18Smcpowers void     s_mp_clamp(mp_int *mp)
2929*f9fbec18Smcpowers {
2930*f9fbec18Smcpowers   mp_size used = MP_USED(mp);
2931*f9fbec18Smcpowers   while (used > 1 && DIGIT(mp, used - 1) == 0)
2932*f9fbec18Smcpowers     --used;
2933*f9fbec18Smcpowers   MP_USED(mp) = used;
2934*f9fbec18Smcpowers } /* end s_mp_clamp() */
2935*f9fbec18Smcpowers #endif
2936*f9fbec18Smcpowers 
2937*f9fbec18Smcpowers /* }}} */
2938*f9fbec18Smcpowers 
2939*f9fbec18Smcpowers /* {{{ s_mp_exch(a, b) */
2940*f9fbec18Smcpowers 
2941*f9fbec18Smcpowers /* Exchange the data for a and b; (b, a) = (a, b)                         */
2942*f9fbec18Smcpowers void     s_mp_exch(mp_int *a, mp_int *b)
2943*f9fbec18Smcpowers {
2944*f9fbec18Smcpowers   mp_int   tmp;
2945*f9fbec18Smcpowers 
2946*f9fbec18Smcpowers   tmp = *a;
2947*f9fbec18Smcpowers   *a = *b;
2948*f9fbec18Smcpowers   *b = tmp;
2949*f9fbec18Smcpowers 
2950*f9fbec18Smcpowers } /* end s_mp_exch() */
2951*f9fbec18Smcpowers 
2952*f9fbec18Smcpowers /* }}} */
2953*f9fbec18Smcpowers 
2954*f9fbec18Smcpowers /* }}} */
2955*f9fbec18Smcpowers 
2956*f9fbec18Smcpowers /* {{{ Arithmetic helpers */
2957*f9fbec18Smcpowers 
2958*f9fbec18Smcpowers /* {{{ s_mp_lshd(mp, p) */
2959*f9fbec18Smcpowers 
2960*f9fbec18Smcpowers /*
2961*f9fbec18Smcpowers    Shift mp leftward by p digits, growing if needed, and zero-filling
2962*f9fbec18Smcpowers    the in-shifted digits at the right end.  This is a convenient
2963*f9fbec18Smcpowers    alternative to multiplication by powers of the radix
2964*f9fbec18Smcpowers    The value of USED(mp) must already have been set to the value for
2965*f9fbec18Smcpowers    the shifted result.
2966*f9fbec18Smcpowers  */
2967*f9fbec18Smcpowers 
2968*f9fbec18Smcpowers mp_err   s_mp_lshd(mp_int *mp, mp_size p)
2969*f9fbec18Smcpowers {
2970*f9fbec18Smcpowers   mp_err  res;
2971*f9fbec18Smcpowers   mp_size pos;
2972*f9fbec18Smcpowers   int     ix;
2973*f9fbec18Smcpowers 
2974*f9fbec18Smcpowers   if(p == 0)
2975*f9fbec18Smcpowers     return MP_OKAY;
2976*f9fbec18Smcpowers 
2977*f9fbec18Smcpowers   if (MP_USED(mp) == 1 && MP_DIGIT(mp, 0) == 0)
2978*f9fbec18Smcpowers     return MP_OKAY;
2979*f9fbec18Smcpowers 
2980*f9fbec18Smcpowers   if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)
2981*f9fbec18Smcpowers     return res;
2982*f9fbec18Smcpowers 
2983*f9fbec18Smcpowers   pos = USED(mp) - 1;
2984*f9fbec18Smcpowers 
2985*f9fbec18Smcpowers   /* Shift all the significant figures over as needed */
2986*f9fbec18Smcpowers   for(ix = pos - p; ix >= 0; ix--)
2987*f9fbec18Smcpowers     DIGIT(mp, ix + p) = DIGIT(mp, ix);
2988*f9fbec18Smcpowers 
2989*f9fbec18Smcpowers   /* Fill the bottom digits with zeroes */
2990*f9fbec18Smcpowers   for(ix = 0; ix < p; ix++)
2991*f9fbec18Smcpowers     DIGIT(mp, ix) = 0;
2992*f9fbec18Smcpowers 
2993*f9fbec18Smcpowers   return MP_OKAY;
2994*f9fbec18Smcpowers 
2995*f9fbec18Smcpowers } /* end s_mp_lshd() */
2996*f9fbec18Smcpowers 
2997*f9fbec18Smcpowers /* }}} */
2998*f9fbec18Smcpowers 
2999*f9fbec18Smcpowers /* {{{ s_mp_mul_2d(mp, d) */
3000*f9fbec18Smcpowers 
3001*f9fbec18Smcpowers /*
3002*f9fbec18Smcpowers   Multiply the integer by 2^d, where d is a number of bits.  This
3003*f9fbec18Smcpowers   amounts to a bitwise shift of the value.
3004*f9fbec18Smcpowers  */
3005*f9fbec18Smcpowers mp_err   s_mp_mul_2d(mp_int *mp, mp_digit d)
3006*f9fbec18Smcpowers {
3007*f9fbec18Smcpowers   mp_err   res;
3008*f9fbec18Smcpowers   mp_digit dshift, bshift;
3009*f9fbec18Smcpowers   mp_digit mask;
3010*f9fbec18Smcpowers 
3011*f9fbec18Smcpowers   ARGCHK(mp != NULL,  MP_BADARG);
3012*f9fbec18Smcpowers 
3013*f9fbec18Smcpowers   dshift = d / MP_DIGIT_BIT;
3014*f9fbec18Smcpowers   bshift = d % MP_DIGIT_BIT;
3015*f9fbec18Smcpowers   /* bits to be shifted out of the top word */
3016*f9fbec18Smcpowers   mask   = ((mp_digit)~0 << (MP_DIGIT_BIT - bshift));
3017*f9fbec18Smcpowers   mask  &= MP_DIGIT(mp, MP_USED(mp) - 1);
3018*f9fbec18Smcpowers 
3019*f9fbec18Smcpowers   if (MP_OKAY != (res = s_mp_pad(mp, MP_USED(mp) + dshift + (mask != 0) )))
3020*f9fbec18Smcpowers     return res;
3021*f9fbec18Smcpowers 
3022*f9fbec18Smcpowers   if (dshift && MP_OKAY != (res = s_mp_lshd(mp, dshift)))
3023*f9fbec18Smcpowers     return res;
3024*f9fbec18Smcpowers 
3025*f9fbec18Smcpowers   if (bshift) {
3026*f9fbec18Smcpowers     mp_digit *pa = MP_DIGITS(mp);
3027*f9fbec18Smcpowers     mp_digit *alim = pa + MP_USED(mp);
3028*f9fbec18Smcpowers     mp_digit  prev = 0;
3029*f9fbec18Smcpowers 
3030*f9fbec18Smcpowers     for (pa += dshift; pa < alim; ) {
3031*f9fbec18Smcpowers       mp_digit x = *pa;
3032*f9fbec18Smcpowers       *pa++ = (x << bshift) | prev;
3033*f9fbec18Smcpowers       prev = x >> (DIGIT_BIT - bshift);
3034*f9fbec18Smcpowers     }
3035*f9fbec18Smcpowers   }
3036*f9fbec18Smcpowers 
3037*f9fbec18Smcpowers   s_mp_clamp(mp);
3038*f9fbec18Smcpowers   return MP_OKAY;
3039*f9fbec18Smcpowers } /* end s_mp_mul_2d() */
3040*f9fbec18Smcpowers 
3041*f9fbec18Smcpowers /* {{{ s_mp_rshd(mp, p) */
3042*f9fbec18Smcpowers 
3043*f9fbec18Smcpowers /*
3044*f9fbec18Smcpowers    Shift mp rightward by p digits.  Maintains the invariant that
3045*f9fbec18Smcpowers    digits above the precision are all zero.  Digits shifted off the
3046*f9fbec18Smcpowers    end are lost.  Cannot fail.
3047*f9fbec18Smcpowers  */
3048*f9fbec18Smcpowers 
3049*f9fbec18Smcpowers void     s_mp_rshd(mp_int *mp, mp_size p)
3050*f9fbec18Smcpowers {
3051*f9fbec18Smcpowers   mp_size  ix;
3052*f9fbec18Smcpowers   mp_digit *src, *dst;
3053*f9fbec18Smcpowers 
3054*f9fbec18Smcpowers   if(p == 0)
3055*f9fbec18Smcpowers     return;
3056*f9fbec18Smcpowers 
3057*f9fbec18Smcpowers   /* Shortcut when all digits are to be shifted off */
3058*f9fbec18Smcpowers   if(p >= USED(mp)) {
3059*f9fbec18Smcpowers     s_mp_setz(DIGITS(mp), ALLOC(mp));
3060*f9fbec18Smcpowers     USED(mp) = 1;
3061*f9fbec18Smcpowers     SIGN(mp) = ZPOS;
3062*f9fbec18Smcpowers     return;
3063*f9fbec18Smcpowers   }
3064*f9fbec18Smcpowers 
3065*f9fbec18Smcpowers   /* Shift all the significant figures over as needed */
3066*f9fbec18Smcpowers   dst = MP_DIGITS(mp);
3067*f9fbec18Smcpowers   src = dst + p;
3068*f9fbec18Smcpowers   for (ix = USED(mp) - p; ix > 0; ix--)
3069*f9fbec18Smcpowers     *dst++ = *src++;
3070*f9fbec18Smcpowers 
3071*f9fbec18Smcpowers   MP_USED(mp) -= p;
3072*f9fbec18Smcpowers   /* Fill the top digits with zeroes */
3073*f9fbec18Smcpowers   while (p-- > 0)
3074*f9fbec18Smcpowers     *dst++ = 0;
3075*f9fbec18Smcpowers 
3076*f9fbec18Smcpowers #if 0
3077*f9fbec18Smcpowers   /* Strip off any leading zeroes    */
3078*f9fbec18Smcpowers   s_mp_clamp(mp);
3079*f9fbec18Smcpowers #endif
3080*f9fbec18Smcpowers 
3081*f9fbec18Smcpowers } /* end s_mp_rshd() */
3082*f9fbec18Smcpowers 
3083*f9fbec18Smcpowers /* }}} */
3084*f9fbec18Smcpowers 
3085*f9fbec18Smcpowers /* {{{ s_mp_div_2(mp) */
3086*f9fbec18Smcpowers 
3087*f9fbec18Smcpowers /* Divide by two -- take advantage of radix properties to do it fast      */
3088*f9fbec18Smcpowers void     s_mp_div_2(mp_int *mp)
3089*f9fbec18Smcpowers {
3090*f9fbec18Smcpowers   s_mp_div_2d(mp, 1);
3091*f9fbec18Smcpowers 
3092*f9fbec18Smcpowers } /* end s_mp_div_2() */
3093*f9fbec18Smcpowers 
3094*f9fbec18Smcpowers /* }}} */
3095*f9fbec18Smcpowers 
3096*f9fbec18Smcpowers /* {{{ s_mp_mul_2(mp) */
3097*f9fbec18Smcpowers 
3098*f9fbec18Smcpowers mp_err s_mp_mul_2(mp_int *mp)
3099*f9fbec18Smcpowers {
3100*f9fbec18Smcpowers   mp_digit *pd;
3101*f9fbec18Smcpowers   int      ix, used;
3102*f9fbec18Smcpowers   mp_digit kin = 0;
3103*f9fbec18Smcpowers 
3104*f9fbec18Smcpowers   /* Shift digits leftward by 1 bit */
3105*f9fbec18Smcpowers   used = MP_USED(mp);
3106*f9fbec18Smcpowers   pd = MP_DIGITS(mp);
3107*f9fbec18Smcpowers   for (ix = 0; ix < used; ix++) {
3108*f9fbec18Smcpowers     mp_digit d = *pd;
3109*f9fbec18Smcpowers     *pd++ = (d << 1) | kin;
3110*f9fbec18Smcpowers     kin = (d >> (DIGIT_BIT - 1));
3111*f9fbec18Smcpowers   }
3112*f9fbec18Smcpowers 
3113*f9fbec18Smcpowers   /* Deal with rollover from last digit */
3114*f9fbec18Smcpowers   if (kin) {
3115*f9fbec18Smcpowers     if (ix >= ALLOC(mp)) {
3116*f9fbec18Smcpowers       mp_err res;
3117*f9fbec18Smcpowers       if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)
3118*f9fbec18Smcpowers 	return res;
3119*f9fbec18Smcpowers     }
3120*f9fbec18Smcpowers 
3121*f9fbec18Smcpowers     DIGIT(mp, ix) = kin;
3122*f9fbec18Smcpowers     USED(mp) += 1;
3123*f9fbec18Smcpowers   }
3124*f9fbec18Smcpowers 
3125*f9fbec18Smcpowers   return MP_OKAY;
3126*f9fbec18Smcpowers 
3127*f9fbec18Smcpowers } /* end s_mp_mul_2() */
3128*f9fbec18Smcpowers 
3129*f9fbec18Smcpowers /* }}} */
3130*f9fbec18Smcpowers 
3131*f9fbec18Smcpowers /* {{{ s_mp_mod_2d(mp, d) */
3132*f9fbec18Smcpowers 
3133*f9fbec18Smcpowers /*
3134*f9fbec18Smcpowers   Remainder the integer by 2^d, where d is a number of bits.  This
3135*f9fbec18Smcpowers   amounts to a bitwise AND of the value, and does not require the full
3136*f9fbec18Smcpowers   division code
3137*f9fbec18Smcpowers  */
3138*f9fbec18Smcpowers void     s_mp_mod_2d(mp_int *mp, mp_digit d)
3139*f9fbec18Smcpowers {
3140*f9fbec18Smcpowers   mp_size  ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);
3141*f9fbec18Smcpowers   mp_size  ix;
3142*f9fbec18Smcpowers   mp_digit dmask;
3143*f9fbec18Smcpowers 
3144*f9fbec18Smcpowers   if(ndig >= USED(mp))
3145*f9fbec18Smcpowers     return;
3146*f9fbec18Smcpowers 
3147*f9fbec18Smcpowers   /* Flush all the bits above 2^d in its digit */
3148*f9fbec18Smcpowers   dmask = ((mp_digit)1 << nbit) - 1;
3149*f9fbec18Smcpowers   DIGIT(mp, ndig) &= dmask;
3150*f9fbec18Smcpowers 
3151*f9fbec18Smcpowers   /* Flush all digits above the one with 2^d in it */
3152*f9fbec18Smcpowers   for(ix = ndig + 1; ix < USED(mp); ix++)
3153*f9fbec18Smcpowers     DIGIT(mp, ix) = 0;
3154*f9fbec18Smcpowers 
3155*f9fbec18Smcpowers   s_mp_clamp(mp);
3156*f9fbec18Smcpowers 
3157*f9fbec18Smcpowers } /* end s_mp_mod_2d() */
3158*f9fbec18Smcpowers 
3159*f9fbec18Smcpowers /* }}} */
3160*f9fbec18Smcpowers 
3161*f9fbec18Smcpowers /* {{{ s_mp_div_2d(mp, d) */
3162*f9fbec18Smcpowers 
3163*f9fbec18Smcpowers /*
3164*f9fbec18Smcpowers   Divide the integer by 2^d, where d is a number of bits.  This
3165*f9fbec18Smcpowers   amounts to a bitwise shift of the value, and does not require the
3166*f9fbec18Smcpowers   full division code (used in Barrett reduction, see below)
3167*f9fbec18Smcpowers  */
3168*f9fbec18Smcpowers void     s_mp_div_2d(mp_int *mp, mp_digit d)
3169*f9fbec18Smcpowers {
3170*f9fbec18Smcpowers   int       ix;
3171*f9fbec18Smcpowers   mp_digit  save, next, mask;
3172*f9fbec18Smcpowers 
3173*f9fbec18Smcpowers   s_mp_rshd(mp, d / DIGIT_BIT);
3174*f9fbec18Smcpowers   d %= DIGIT_BIT;
3175*f9fbec18Smcpowers   if (d) {
3176*f9fbec18Smcpowers     mask = ((mp_digit)1 << d) - 1;
3177*f9fbec18Smcpowers     save = 0;
3178*f9fbec18Smcpowers     for(ix = USED(mp) - 1; ix >= 0; ix--) {
3179*f9fbec18Smcpowers       next = DIGIT(mp, ix) & mask;
3180*f9fbec18Smcpowers       DIGIT(mp, ix) = (DIGIT(mp, ix) >> d) | (save << (DIGIT_BIT - d));
3181*f9fbec18Smcpowers       save = next;
3182*f9fbec18Smcpowers     }
3183*f9fbec18Smcpowers   }
3184*f9fbec18Smcpowers   s_mp_clamp(mp);
3185*f9fbec18Smcpowers 
3186*f9fbec18Smcpowers } /* end s_mp_div_2d() */
3187*f9fbec18Smcpowers 
3188*f9fbec18Smcpowers /* }}} */
3189*f9fbec18Smcpowers 
3190*f9fbec18Smcpowers /* {{{ s_mp_norm(a, b, *d) */
3191*f9fbec18Smcpowers 
3192*f9fbec18Smcpowers /*
3193*f9fbec18Smcpowers   s_mp_norm(a, b, *d)
3194*f9fbec18Smcpowers 
3195*f9fbec18Smcpowers   Normalize a and b for division, where b is the divisor.  In order
3196*f9fbec18Smcpowers   that we might make good guesses for quotient digits, we want the
3197*f9fbec18Smcpowers   leading digit of b to be at least half the radix, which we
3198*f9fbec18Smcpowers   accomplish by multiplying a and b by a power of 2.  The exponent
3199*f9fbec18Smcpowers   (shift count) is placed in *pd, so that the remainder can be shifted
3200*f9fbec18Smcpowers   back at the end of the division process.
3201*f9fbec18Smcpowers  */
3202*f9fbec18Smcpowers 
3203*f9fbec18Smcpowers mp_err   s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd)
3204*f9fbec18Smcpowers {
3205*f9fbec18Smcpowers   mp_digit  d;
3206*f9fbec18Smcpowers   mp_digit  mask;
3207*f9fbec18Smcpowers   mp_digit  b_msd;
3208*f9fbec18Smcpowers   mp_err    res    = MP_OKAY;
3209*f9fbec18Smcpowers 
3210*f9fbec18Smcpowers   d = 0;
3211*f9fbec18Smcpowers   mask  = DIGIT_MAX & ~(DIGIT_MAX >> 1);	/* mask is msb of digit */
3212*f9fbec18Smcpowers   b_msd = DIGIT(b, USED(b) - 1);
3213*f9fbec18Smcpowers   while (!(b_msd & mask)) {
3214*f9fbec18Smcpowers     b_msd <<= 1;
3215*f9fbec18Smcpowers     ++d;
3216*f9fbec18Smcpowers   }
3217*f9fbec18Smcpowers 
3218*f9fbec18Smcpowers   if (d) {
3219*f9fbec18Smcpowers     MP_CHECKOK( s_mp_mul_2d(a, d) );
3220*f9fbec18Smcpowers     MP_CHECKOK( s_mp_mul_2d(b, d) );
3221*f9fbec18Smcpowers   }
3222*f9fbec18Smcpowers 
3223*f9fbec18Smcpowers   *pd = d;
3224*f9fbec18Smcpowers CLEANUP:
3225*f9fbec18Smcpowers   return res;
3226*f9fbec18Smcpowers 
3227*f9fbec18Smcpowers } /* end s_mp_norm() */
3228*f9fbec18Smcpowers 
3229*f9fbec18Smcpowers /* }}} */
3230*f9fbec18Smcpowers 
3231*f9fbec18Smcpowers /* }}} */
3232*f9fbec18Smcpowers 
3233*f9fbec18Smcpowers /* {{{ Primitive digit arithmetic */
3234*f9fbec18Smcpowers 
3235*f9fbec18Smcpowers /* {{{ s_mp_add_d(mp, d) */
3236*f9fbec18Smcpowers 
3237*f9fbec18Smcpowers /* Add d to |mp| in place                                                 */
3238*f9fbec18Smcpowers mp_err   s_mp_add_d(mp_int *mp, mp_digit d)    /* unsigned digit addition */
3239*f9fbec18Smcpowers {
3240*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3241*f9fbec18Smcpowers   mp_word   w, k = 0;
3242*f9fbec18Smcpowers   mp_size   ix = 1;
3243*f9fbec18Smcpowers 
3244*f9fbec18Smcpowers   w = (mp_word)DIGIT(mp, 0) + d;
3245*f9fbec18Smcpowers   DIGIT(mp, 0) = ACCUM(w);
3246*f9fbec18Smcpowers   k = CARRYOUT(w);
3247*f9fbec18Smcpowers 
3248*f9fbec18Smcpowers   while(ix < USED(mp) && k) {
3249*f9fbec18Smcpowers     w = (mp_word)DIGIT(mp, ix) + k;
3250*f9fbec18Smcpowers     DIGIT(mp, ix) = ACCUM(w);
3251*f9fbec18Smcpowers     k = CARRYOUT(w);
3252*f9fbec18Smcpowers     ++ix;
3253*f9fbec18Smcpowers   }
3254*f9fbec18Smcpowers 
3255*f9fbec18Smcpowers   if(k != 0) {
3256*f9fbec18Smcpowers     mp_err  res;
3257*f9fbec18Smcpowers 
3258*f9fbec18Smcpowers     if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)
3259*f9fbec18Smcpowers       return res;
3260*f9fbec18Smcpowers 
3261*f9fbec18Smcpowers     DIGIT(mp, ix) = (mp_digit)k;
3262*f9fbec18Smcpowers   }
3263*f9fbec18Smcpowers 
3264*f9fbec18Smcpowers   return MP_OKAY;
3265*f9fbec18Smcpowers #else
3266*f9fbec18Smcpowers   mp_digit * pmp = MP_DIGITS(mp);
3267*f9fbec18Smcpowers   mp_digit sum, mp_i, carry = 0;
3268*f9fbec18Smcpowers   mp_err   res = MP_OKAY;
3269*f9fbec18Smcpowers   int used = (int)MP_USED(mp);
3270*f9fbec18Smcpowers 
3271*f9fbec18Smcpowers   mp_i = *pmp;
3272*f9fbec18Smcpowers   *pmp++ = sum = d + mp_i;
3273*f9fbec18Smcpowers   carry = (sum < d);
3274*f9fbec18Smcpowers   while (carry && --used > 0) {
3275*f9fbec18Smcpowers     mp_i = *pmp;
3276*f9fbec18Smcpowers     *pmp++ = sum = carry + mp_i;
3277*f9fbec18Smcpowers     carry = !sum;
3278*f9fbec18Smcpowers   }
3279*f9fbec18Smcpowers   if (carry && !used) {
3280*f9fbec18Smcpowers     /* mp is growing */
3281*f9fbec18Smcpowers     used = MP_USED(mp);
3282*f9fbec18Smcpowers     MP_CHECKOK( s_mp_pad(mp, used + 1) );
3283*f9fbec18Smcpowers     MP_DIGIT(mp, used) = carry;
3284*f9fbec18Smcpowers   }
3285*f9fbec18Smcpowers CLEANUP:
3286*f9fbec18Smcpowers   return res;
3287*f9fbec18Smcpowers #endif
3288*f9fbec18Smcpowers } /* end s_mp_add_d() */
3289*f9fbec18Smcpowers 
3290*f9fbec18Smcpowers /* }}} */
3291*f9fbec18Smcpowers 
3292*f9fbec18Smcpowers /* {{{ s_mp_sub_d(mp, d) */
3293*f9fbec18Smcpowers 
3294*f9fbec18Smcpowers /* Subtract d from |mp| in place, assumes |mp| > d                        */
3295*f9fbec18Smcpowers mp_err   s_mp_sub_d(mp_int *mp, mp_digit d)    /* unsigned digit subtract */
3296*f9fbec18Smcpowers {
3297*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3298*f9fbec18Smcpowers   mp_word   w, b = 0;
3299*f9fbec18Smcpowers   mp_size   ix = 1;
3300*f9fbec18Smcpowers 
3301*f9fbec18Smcpowers   /* Compute initial subtraction    */
3302*f9fbec18Smcpowers   w = (RADIX + (mp_word)DIGIT(mp, 0)) - d;
3303*f9fbec18Smcpowers   b = CARRYOUT(w) ? 0 : 1;
3304*f9fbec18Smcpowers   DIGIT(mp, 0) = ACCUM(w);
3305*f9fbec18Smcpowers 
3306*f9fbec18Smcpowers   /* Propagate borrows leftward     */
3307*f9fbec18Smcpowers   while(b && ix < USED(mp)) {
3308*f9fbec18Smcpowers     w = (RADIX + (mp_word)DIGIT(mp, ix)) - b;
3309*f9fbec18Smcpowers     b = CARRYOUT(w) ? 0 : 1;
3310*f9fbec18Smcpowers     DIGIT(mp, ix) = ACCUM(w);
3311*f9fbec18Smcpowers     ++ix;
3312*f9fbec18Smcpowers   }
3313*f9fbec18Smcpowers 
3314*f9fbec18Smcpowers   /* Remove leading zeroes          */
3315*f9fbec18Smcpowers   s_mp_clamp(mp);
3316*f9fbec18Smcpowers 
3317*f9fbec18Smcpowers   /* If we have a borrow out, it's a violation of the input invariant */
3318*f9fbec18Smcpowers   if(b)
3319*f9fbec18Smcpowers     return MP_RANGE;
3320*f9fbec18Smcpowers   else
3321*f9fbec18Smcpowers     return MP_OKAY;
3322*f9fbec18Smcpowers #else
3323*f9fbec18Smcpowers   mp_digit *pmp = MP_DIGITS(mp);
3324*f9fbec18Smcpowers   mp_digit mp_i, diff, borrow;
3325*f9fbec18Smcpowers   mp_size  used = MP_USED(mp);
3326*f9fbec18Smcpowers 
3327*f9fbec18Smcpowers   mp_i = *pmp;
3328*f9fbec18Smcpowers   *pmp++ = diff = mp_i - d;
3329*f9fbec18Smcpowers   borrow = (diff > mp_i);
3330*f9fbec18Smcpowers   while (borrow && --used) {
3331*f9fbec18Smcpowers     mp_i = *pmp;
3332*f9fbec18Smcpowers     *pmp++ = diff = mp_i - borrow;
3333*f9fbec18Smcpowers     borrow = (diff > mp_i);
3334*f9fbec18Smcpowers   }
3335*f9fbec18Smcpowers   s_mp_clamp(mp);
3336*f9fbec18Smcpowers   return (borrow && !used) ? MP_RANGE : MP_OKAY;
3337*f9fbec18Smcpowers #endif
3338*f9fbec18Smcpowers } /* end s_mp_sub_d() */
3339*f9fbec18Smcpowers 
3340*f9fbec18Smcpowers /* }}} */
3341*f9fbec18Smcpowers 
3342*f9fbec18Smcpowers /* {{{ s_mp_mul_d(a, d) */
3343*f9fbec18Smcpowers 
3344*f9fbec18Smcpowers /* Compute a = a * d, single digit multiplication                         */
3345*f9fbec18Smcpowers mp_err   s_mp_mul_d(mp_int *a, mp_digit d)
3346*f9fbec18Smcpowers {
3347*f9fbec18Smcpowers   mp_err  res;
3348*f9fbec18Smcpowers   mp_size used;
3349*f9fbec18Smcpowers   int     pow;
3350*f9fbec18Smcpowers 
3351*f9fbec18Smcpowers   if (!d) {
3352*f9fbec18Smcpowers     mp_zero(a);
3353*f9fbec18Smcpowers     return MP_OKAY;
3354*f9fbec18Smcpowers   }
3355*f9fbec18Smcpowers   if (d == 1)
3356*f9fbec18Smcpowers     return MP_OKAY;
3357*f9fbec18Smcpowers   if (0 <= (pow = s_mp_ispow2d(d))) {
3358*f9fbec18Smcpowers     return s_mp_mul_2d(a, (mp_digit)pow);
3359*f9fbec18Smcpowers   }
3360*f9fbec18Smcpowers 
3361*f9fbec18Smcpowers   used = MP_USED(a);
3362*f9fbec18Smcpowers   MP_CHECKOK( s_mp_pad(a, used + 1) );
3363*f9fbec18Smcpowers 
3364*f9fbec18Smcpowers   s_mpv_mul_d(MP_DIGITS(a), used, d, MP_DIGITS(a));
3365*f9fbec18Smcpowers 
3366*f9fbec18Smcpowers   s_mp_clamp(a);
3367*f9fbec18Smcpowers 
3368*f9fbec18Smcpowers CLEANUP:
3369*f9fbec18Smcpowers   return res;
3370*f9fbec18Smcpowers 
3371*f9fbec18Smcpowers } /* end s_mp_mul_d() */
3372*f9fbec18Smcpowers 
3373*f9fbec18Smcpowers /* }}} */
3374*f9fbec18Smcpowers 
3375*f9fbec18Smcpowers /* {{{ s_mp_div_d(mp, d, r) */
3376*f9fbec18Smcpowers 
3377*f9fbec18Smcpowers /*
3378*f9fbec18Smcpowers   s_mp_div_d(mp, d, r)
3379*f9fbec18Smcpowers 
3380*f9fbec18Smcpowers   Compute the quotient mp = mp / d and remainder r = mp mod d, for a
3381*f9fbec18Smcpowers   single digit d.  If r is null, the remainder will be discarded.
3382*f9fbec18Smcpowers  */
3383*f9fbec18Smcpowers 
3384*f9fbec18Smcpowers mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
3385*f9fbec18Smcpowers {
3386*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
3387*f9fbec18Smcpowers   mp_word   w = 0, q;
3388*f9fbec18Smcpowers #else
3389*f9fbec18Smcpowers   mp_digit  w, q;
3390*f9fbec18Smcpowers #endif
3391*f9fbec18Smcpowers   int       ix;
3392*f9fbec18Smcpowers   mp_err    res;
3393*f9fbec18Smcpowers   mp_int    quot;
3394*f9fbec18Smcpowers   mp_int    rem;
3395*f9fbec18Smcpowers 
3396*f9fbec18Smcpowers   if(d == 0)
3397*f9fbec18Smcpowers     return MP_RANGE;
3398*f9fbec18Smcpowers   if (d == 1) {
3399*f9fbec18Smcpowers     if (r)
3400*f9fbec18Smcpowers       *r = 0;
3401*f9fbec18Smcpowers     return MP_OKAY;
3402*f9fbec18Smcpowers   }
3403*f9fbec18Smcpowers   /* could check for power of 2 here, but mp_div_d does that. */
3404*f9fbec18Smcpowers   if (MP_USED(mp) == 1) {
3405*f9fbec18Smcpowers     mp_digit n   = MP_DIGIT(mp,0);
3406*f9fbec18Smcpowers     mp_digit rem;
3407*f9fbec18Smcpowers 
3408*f9fbec18Smcpowers     q   = n / d;
3409*f9fbec18Smcpowers     rem = n % d;
3410*f9fbec18Smcpowers     MP_DIGIT(mp,0) = q;
3411*f9fbec18Smcpowers     if (r)
3412*f9fbec18Smcpowers       *r = rem;
3413*f9fbec18Smcpowers     return MP_OKAY;
3414*f9fbec18Smcpowers   }
3415*f9fbec18Smcpowers 
3416*f9fbec18Smcpowers   MP_DIGITS(&rem)  = 0;
3417*f9fbec18Smcpowers   MP_DIGITS(&quot) = 0;
3418*f9fbec18Smcpowers   /* Make room for the quotient */
3419*f9fbec18Smcpowers   MP_CHECKOK( mp_init_size(&quot, USED(mp), FLAG(mp)) );
3420*f9fbec18Smcpowers 
3421*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
3422*f9fbec18Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
3423*f9fbec18Smcpowers     w = (w << DIGIT_BIT) | DIGIT(mp, ix);
3424*f9fbec18Smcpowers 
3425*f9fbec18Smcpowers     if(w >= d) {
3426*f9fbec18Smcpowers       q = w / d;
3427*f9fbec18Smcpowers       w = w % d;
3428*f9fbec18Smcpowers     } else {
3429*f9fbec18Smcpowers       q = 0;
3430*f9fbec18Smcpowers     }
3431*f9fbec18Smcpowers 
3432*f9fbec18Smcpowers     s_mp_lshd(&quot, 1);
3433*f9fbec18Smcpowers     DIGIT(&quot, 0) = (mp_digit)q;
3434*f9fbec18Smcpowers   }
3435*f9fbec18Smcpowers #else
3436*f9fbec18Smcpowers   {
3437*f9fbec18Smcpowers     mp_digit p;
3438*f9fbec18Smcpowers #if !defined(MP_ASSEMBLY_DIV_2DX1D)
3439*f9fbec18Smcpowers     mp_digit norm;
3440*f9fbec18Smcpowers #endif
3441*f9fbec18Smcpowers 
3442*f9fbec18Smcpowers     MP_CHECKOK( mp_init_copy(&rem, mp) );
3443*f9fbec18Smcpowers 
3444*f9fbec18Smcpowers #if !defined(MP_ASSEMBLY_DIV_2DX1D)
3445*f9fbec18Smcpowers     MP_DIGIT(&quot, 0) = d;
3446*f9fbec18Smcpowers     MP_CHECKOK( s_mp_norm(&rem, &quot, &norm) );
3447*f9fbec18Smcpowers     if (norm)
3448*f9fbec18Smcpowers       d <<= norm;
3449*f9fbec18Smcpowers     MP_DIGIT(&quot, 0) = 0;
3450*f9fbec18Smcpowers #endif
3451*f9fbec18Smcpowers 
3452*f9fbec18Smcpowers     p = 0;
3453*f9fbec18Smcpowers     for (ix = USED(&rem) - 1; ix >= 0; ix--) {
3454*f9fbec18Smcpowers       w = DIGIT(&rem, ix);
3455*f9fbec18Smcpowers 
3456*f9fbec18Smcpowers       if (p) {
3457*f9fbec18Smcpowers         MP_CHECKOK( s_mpv_div_2dx1d(p, w, d, &q, &w) );
3458*f9fbec18Smcpowers       } else if (w >= d) {
3459*f9fbec18Smcpowers 	q = w / d;
3460*f9fbec18Smcpowers 	w = w % d;
3461*f9fbec18Smcpowers       } else {
3462*f9fbec18Smcpowers 	q = 0;
3463*f9fbec18Smcpowers       }
3464*f9fbec18Smcpowers 
3465*f9fbec18Smcpowers       MP_CHECKOK( s_mp_lshd(&quot, 1) );
3466*f9fbec18Smcpowers       DIGIT(&quot, 0) = q;
3467*f9fbec18Smcpowers       p = w;
3468*f9fbec18Smcpowers     }
3469*f9fbec18Smcpowers #if !defined(MP_ASSEMBLY_DIV_2DX1D)
3470*f9fbec18Smcpowers     if (norm)
3471*f9fbec18Smcpowers       w >>= norm;
3472*f9fbec18Smcpowers #endif
3473*f9fbec18Smcpowers   }
3474*f9fbec18Smcpowers #endif
3475*f9fbec18Smcpowers 
3476*f9fbec18Smcpowers   /* Deliver the remainder, if desired */
3477*f9fbec18Smcpowers   if(r)
3478*f9fbec18Smcpowers     *r = (mp_digit)w;
3479*f9fbec18Smcpowers 
3480*f9fbec18Smcpowers   s_mp_clamp(&quot);
3481*f9fbec18Smcpowers   mp_exch(&quot, mp);
3482*f9fbec18Smcpowers CLEANUP:
3483*f9fbec18Smcpowers   mp_clear(&quot);
3484*f9fbec18Smcpowers   mp_clear(&rem);
3485*f9fbec18Smcpowers 
3486*f9fbec18Smcpowers   return res;
3487*f9fbec18Smcpowers } /* end s_mp_div_d() */
3488*f9fbec18Smcpowers 
3489*f9fbec18Smcpowers /* }}} */
3490*f9fbec18Smcpowers 
3491*f9fbec18Smcpowers 
3492*f9fbec18Smcpowers /* }}} */
3493*f9fbec18Smcpowers 
3494*f9fbec18Smcpowers /* {{{ Primitive full arithmetic */
3495*f9fbec18Smcpowers 
3496*f9fbec18Smcpowers /* {{{ s_mp_add(a, b) */
3497*f9fbec18Smcpowers 
3498*f9fbec18Smcpowers /* Compute a = |a| + |b|                                                  */
3499*f9fbec18Smcpowers mp_err   s_mp_add(mp_int *a, const mp_int *b)  /* magnitude addition      */
3500*f9fbec18Smcpowers {
3501*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3502*f9fbec18Smcpowers   mp_word   w = 0;
3503*f9fbec18Smcpowers #else
3504*f9fbec18Smcpowers   mp_digit  d, sum, carry = 0;
3505*f9fbec18Smcpowers #endif
3506*f9fbec18Smcpowers   mp_digit *pa, *pb;
3507*f9fbec18Smcpowers   mp_size   ix;
3508*f9fbec18Smcpowers   mp_size   used;
3509*f9fbec18Smcpowers   mp_err    res;
3510*f9fbec18Smcpowers 
3511*f9fbec18Smcpowers   /* Make sure a has enough precision for the output value */
3512*f9fbec18Smcpowers   if((USED(b) > USED(a)) && (res = s_mp_pad(a, USED(b))) != MP_OKAY)
3513*f9fbec18Smcpowers     return res;
3514*f9fbec18Smcpowers 
3515*f9fbec18Smcpowers   /*
3516*f9fbec18Smcpowers     Add up all digits up to the precision of b.  If b had initially
3517*f9fbec18Smcpowers     the same precision as a, or greater, we took care of it by the
3518*f9fbec18Smcpowers     padding step above, so there is no problem.  If b had initially
3519*f9fbec18Smcpowers     less precision, we'll have to make sure the carry out is duly
3520*f9fbec18Smcpowers     propagated upward among the higher-order digits of the sum.
3521*f9fbec18Smcpowers    */
3522*f9fbec18Smcpowers   pa = MP_DIGITS(a);
3523*f9fbec18Smcpowers   pb = MP_DIGITS(b);
3524*f9fbec18Smcpowers   used = MP_USED(b);
3525*f9fbec18Smcpowers   for(ix = 0; ix < used; ix++) {
3526*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3527*f9fbec18Smcpowers     w = w + *pa + *pb++;
3528*f9fbec18Smcpowers     *pa++ = ACCUM(w);
3529*f9fbec18Smcpowers     w = CARRYOUT(w);
3530*f9fbec18Smcpowers #else
3531*f9fbec18Smcpowers     d = *pa;
3532*f9fbec18Smcpowers     sum = d + *pb++;
3533*f9fbec18Smcpowers     d = (sum < d);			/* detect overflow */
3534*f9fbec18Smcpowers     *pa++ = sum += carry;
3535*f9fbec18Smcpowers     carry = d + (sum < carry);		/* detect overflow */
3536*f9fbec18Smcpowers #endif
3537*f9fbec18Smcpowers   }
3538*f9fbec18Smcpowers 
3539*f9fbec18Smcpowers   /* If we run out of 'b' digits before we're actually done, make
3540*f9fbec18Smcpowers      sure the carries get propagated upward...
3541*f9fbec18Smcpowers    */
3542*f9fbec18Smcpowers   used = MP_USED(a);
3543*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3544*f9fbec18Smcpowers   while (w && ix < used) {
3545*f9fbec18Smcpowers     w = w + *pa;
3546*f9fbec18Smcpowers     *pa++ = ACCUM(w);
3547*f9fbec18Smcpowers     w = CARRYOUT(w);
3548*f9fbec18Smcpowers     ++ix;
3549*f9fbec18Smcpowers   }
3550*f9fbec18Smcpowers #else
3551*f9fbec18Smcpowers   while (carry && ix < used) {
3552*f9fbec18Smcpowers     sum = carry + *pa;
3553*f9fbec18Smcpowers     *pa++ = sum;
3554*f9fbec18Smcpowers     carry = !sum;
3555*f9fbec18Smcpowers     ++ix;
3556*f9fbec18Smcpowers   }
3557*f9fbec18Smcpowers #endif
3558*f9fbec18Smcpowers 
3559*f9fbec18Smcpowers   /* If there's an overall carry out, increase precision and include
3560*f9fbec18Smcpowers      it.  We could have done this initially, but why touch the memory
3561*f9fbec18Smcpowers      allocator unless we're sure we have to?
3562*f9fbec18Smcpowers    */
3563*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3564*f9fbec18Smcpowers   if (w) {
3565*f9fbec18Smcpowers     if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
3566*f9fbec18Smcpowers       return res;
3567*f9fbec18Smcpowers 
3568*f9fbec18Smcpowers     DIGIT(a, ix) = (mp_digit)w;
3569*f9fbec18Smcpowers   }
3570*f9fbec18Smcpowers #else
3571*f9fbec18Smcpowers   if (carry) {
3572*f9fbec18Smcpowers     if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
3573*f9fbec18Smcpowers       return res;
3574*f9fbec18Smcpowers 
3575*f9fbec18Smcpowers     DIGIT(a, used) = carry;
3576*f9fbec18Smcpowers   }
3577*f9fbec18Smcpowers #endif
3578*f9fbec18Smcpowers 
3579*f9fbec18Smcpowers   return MP_OKAY;
3580*f9fbec18Smcpowers } /* end s_mp_add() */
3581*f9fbec18Smcpowers 
3582*f9fbec18Smcpowers /* }}} */
3583*f9fbec18Smcpowers 
3584*f9fbec18Smcpowers /* Compute c = |a| + |b|         */ /* magnitude addition      */
3585*f9fbec18Smcpowers mp_err   s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c)
3586*f9fbec18Smcpowers {
3587*f9fbec18Smcpowers   mp_digit *pa, *pb, *pc;
3588*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3589*f9fbec18Smcpowers   mp_word   w = 0;
3590*f9fbec18Smcpowers #else
3591*f9fbec18Smcpowers   mp_digit  sum, carry = 0, d;
3592*f9fbec18Smcpowers #endif
3593*f9fbec18Smcpowers   mp_size   ix;
3594*f9fbec18Smcpowers   mp_size   used;
3595*f9fbec18Smcpowers   mp_err    res;
3596*f9fbec18Smcpowers 
3597*f9fbec18Smcpowers   MP_SIGN(c) = MP_SIGN(a);
3598*f9fbec18Smcpowers   if (MP_USED(a) < MP_USED(b)) {
3599*f9fbec18Smcpowers     const mp_int *xch = a;
3600*f9fbec18Smcpowers     a = b;
3601*f9fbec18Smcpowers     b = xch;
3602*f9fbec18Smcpowers   }
3603*f9fbec18Smcpowers 
3604*f9fbec18Smcpowers   /* Make sure a has enough precision for the output value */
3605*f9fbec18Smcpowers   if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a))))
3606*f9fbec18Smcpowers     return res;
3607*f9fbec18Smcpowers 
3608*f9fbec18Smcpowers   /*
3609*f9fbec18Smcpowers     Add up all digits up to the precision of b.  If b had initially
3610*f9fbec18Smcpowers     the same precision as a, or greater, we took care of it by the
3611*f9fbec18Smcpowers     exchange step above, so there is no problem.  If b had initially
3612*f9fbec18Smcpowers     less precision, we'll have to make sure the carry out is duly
3613*f9fbec18Smcpowers     propagated upward among the higher-order digits of the sum.
3614*f9fbec18Smcpowers    */
3615*f9fbec18Smcpowers   pa = MP_DIGITS(a);
3616*f9fbec18Smcpowers   pb = MP_DIGITS(b);
3617*f9fbec18Smcpowers   pc = MP_DIGITS(c);
3618*f9fbec18Smcpowers   used = MP_USED(b);
3619*f9fbec18Smcpowers   for (ix = 0; ix < used; ix++) {
3620*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3621*f9fbec18Smcpowers     w = w + *pa++ + *pb++;
3622*f9fbec18Smcpowers     *pc++ = ACCUM(w);
3623*f9fbec18Smcpowers     w = CARRYOUT(w);
3624*f9fbec18Smcpowers #else
3625*f9fbec18Smcpowers     d = *pa++;
3626*f9fbec18Smcpowers     sum = d + *pb++;
3627*f9fbec18Smcpowers     d = (sum < d);			/* detect overflow */
3628*f9fbec18Smcpowers     *pc++ = sum += carry;
3629*f9fbec18Smcpowers     carry = d + (sum < carry);		/* detect overflow */
3630*f9fbec18Smcpowers #endif
3631*f9fbec18Smcpowers   }
3632*f9fbec18Smcpowers 
3633*f9fbec18Smcpowers   /* If we run out of 'b' digits before we're actually done, make
3634*f9fbec18Smcpowers      sure the carries get propagated upward...
3635*f9fbec18Smcpowers    */
3636*f9fbec18Smcpowers   for (used = MP_USED(a); ix < used; ++ix) {
3637*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3638*f9fbec18Smcpowers     w = w + *pa++;
3639*f9fbec18Smcpowers     *pc++ = ACCUM(w);
3640*f9fbec18Smcpowers     w = CARRYOUT(w);
3641*f9fbec18Smcpowers #else
3642*f9fbec18Smcpowers     *pc++ = sum = carry + *pa++;
3643*f9fbec18Smcpowers     carry = (sum < carry);
3644*f9fbec18Smcpowers #endif
3645*f9fbec18Smcpowers   }
3646*f9fbec18Smcpowers 
3647*f9fbec18Smcpowers   /* If there's an overall carry out, increase precision and include
3648*f9fbec18Smcpowers      it.  We could have done this initially, but why touch the memory
3649*f9fbec18Smcpowers      allocator unless we're sure we have to?
3650*f9fbec18Smcpowers    */
3651*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3652*f9fbec18Smcpowers   if (w) {
3653*f9fbec18Smcpowers     if((res = s_mp_pad(c, used + 1)) != MP_OKAY)
3654*f9fbec18Smcpowers       return res;
3655*f9fbec18Smcpowers 
3656*f9fbec18Smcpowers     DIGIT(c, used) = (mp_digit)w;
3657*f9fbec18Smcpowers     ++used;
3658*f9fbec18Smcpowers   }
3659*f9fbec18Smcpowers #else
3660*f9fbec18Smcpowers   if (carry) {
3661*f9fbec18Smcpowers     if((res = s_mp_pad(c, used + 1)) != MP_OKAY)
3662*f9fbec18Smcpowers       return res;
3663*f9fbec18Smcpowers 
3664*f9fbec18Smcpowers     DIGIT(c, used) = carry;
3665*f9fbec18Smcpowers     ++used;
3666*f9fbec18Smcpowers   }
3667*f9fbec18Smcpowers #endif
3668*f9fbec18Smcpowers   MP_USED(c) = used;
3669*f9fbec18Smcpowers   return MP_OKAY;
3670*f9fbec18Smcpowers }
3671*f9fbec18Smcpowers /* {{{ s_mp_add_offset(a, b, offset) */
3672*f9fbec18Smcpowers 
3673*f9fbec18Smcpowers /* Compute a = |a| + ( |b| * (RADIX ** offset) )             */
3674*f9fbec18Smcpowers mp_err   s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset)
3675*f9fbec18Smcpowers {
3676*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3677*f9fbec18Smcpowers   mp_word   w, k = 0;
3678*f9fbec18Smcpowers #else
3679*f9fbec18Smcpowers   mp_digit  d, sum, carry = 0;
3680*f9fbec18Smcpowers #endif
3681*f9fbec18Smcpowers   mp_size   ib;
3682*f9fbec18Smcpowers   mp_size   ia;
3683*f9fbec18Smcpowers   mp_size   lim;
3684*f9fbec18Smcpowers   mp_err    res;
3685*f9fbec18Smcpowers 
3686*f9fbec18Smcpowers   /* Make sure a has enough precision for the output value */
3687*f9fbec18Smcpowers   lim = MP_USED(b) + offset;
3688*f9fbec18Smcpowers   if((lim > USED(a)) && (res = s_mp_pad(a, lim)) != MP_OKAY)
3689*f9fbec18Smcpowers     return res;
3690*f9fbec18Smcpowers 
3691*f9fbec18Smcpowers   /*
3692*f9fbec18Smcpowers     Add up all digits up to the precision of b.  If b had initially
3693*f9fbec18Smcpowers     the same precision as a, or greater, we took care of it by the
3694*f9fbec18Smcpowers     padding step above, so there is no problem.  If b had initially
3695*f9fbec18Smcpowers     less precision, we'll have to make sure the carry out is duly
3696*f9fbec18Smcpowers     propagated upward among the higher-order digits of the sum.
3697*f9fbec18Smcpowers    */
3698*f9fbec18Smcpowers   lim = USED(b);
3699*f9fbec18Smcpowers   for(ib = 0, ia = offset; ib < lim; ib++, ia++) {
3700*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3701*f9fbec18Smcpowers     w = (mp_word)DIGIT(a, ia) + DIGIT(b, ib) + k;
3702*f9fbec18Smcpowers     DIGIT(a, ia) = ACCUM(w);
3703*f9fbec18Smcpowers     k = CARRYOUT(w);
3704*f9fbec18Smcpowers #else
3705*f9fbec18Smcpowers     d = MP_DIGIT(a, ia);
3706*f9fbec18Smcpowers     sum = d + MP_DIGIT(b, ib);
3707*f9fbec18Smcpowers     d = (sum < d);
3708*f9fbec18Smcpowers     MP_DIGIT(a,ia) = sum += carry;
3709*f9fbec18Smcpowers     carry = d + (sum < carry);
3710*f9fbec18Smcpowers #endif
3711*f9fbec18Smcpowers   }
3712*f9fbec18Smcpowers 
3713*f9fbec18Smcpowers   /* If we run out of 'b' digits before we're actually done, make
3714*f9fbec18Smcpowers      sure the carries get propagated upward...
3715*f9fbec18Smcpowers    */
3716*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3717*f9fbec18Smcpowers   for (lim = MP_USED(a); k && (ia < lim); ++ia) {
3718*f9fbec18Smcpowers     w = (mp_word)DIGIT(a, ia) + k;
3719*f9fbec18Smcpowers     DIGIT(a, ia) = ACCUM(w);
3720*f9fbec18Smcpowers     k = CARRYOUT(w);
3721*f9fbec18Smcpowers   }
3722*f9fbec18Smcpowers #else
3723*f9fbec18Smcpowers   for (lim = MP_USED(a); carry && (ia < lim); ++ia) {
3724*f9fbec18Smcpowers     d = MP_DIGIT(a, ia);
3725*f9fbec18Smcpowers     MP_DIGIT(a,ia) = sum = d + carry;
3726*f9fbec18Smcpowers     carry = (sum < d);
3727*f9fbec18Smcpowers   }
3728*f9fbec18Smcpowers #endif
3729*f9fbec18Smcpowers 
3730*f9fbec18Smcpowers   /* If there's an overall carry out, increase precision and include
3731*f9fbec18Smcpowers      it.  We could have done this initially, but why touch the memory
3732*f9fbec18Smcpowers      allocator unless we're sure we have to?
3733*f9fbec18Smcpowers    */
3734*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
3735*f9fbec18Smcpowers   if(k) {
3736*f9fbec18Smcpowers     if((res = s_mp_pad(a, USED(a) + 1)) != MP_OKAY)
3737*f9fbec18Smcpowers       return res;
3738*f9fbec18Smcpowers 
3739*f9fbec18Smcpowers     DIGIT(a, ia) = (mp_digit)k;
3740*f9fbec18Smcpowers   }
3741*f9fbec18Smcpowers #else
3742*f9fbec18Smcpowers   if (carry) {
3743*f9fbec18Smcpowers     if((res = s_mp_pad(a, lim + 1)) != MP_OKAY)
3744*f9fbec18Smcpowers       return res;
3745*f9fbec18Smcpowers 
3746*f9fbec18Smcpowers     DIGIT(a, lim) = carry;
3747*f9fbec18Smcpowers   }
3748*f9fbec18Smcpowers #endif
3749*f9fbec18Smcpowers   s_mp_clamp(a);
3750*f9fbec18Smcpowers 
3751*f9fbec18Smcpowers   return MP_OKAY;
3752*f9fbec18Smcpowers 
3753*f9fbec18Smcpowers } /* end s_mp_add_offset() */
3754*f9fbec18Smcpowers 
3755*f9fbec18Smcpowers /* }}} */
3756*f9fbec18Smcpowers 
3757*f9fbec18Smcpowers /* {{{ s_mp_sub(a, b) */
3758*f9fbec18Smcpowers 
3759*f9fbec18Smcpowers /* Compute a = |a| - |b|, assumes |a| >= |b|                              */
3760*f9fbec18Smcpowers mp_err   s_mp_sub(mp_int *a, const mp_int *b)  /* magnitude subtract      */
3761*f9fbec18Smcpowers {
3762*f9fbec18Smcpowers   mp_digit *pa, *pb, *limit;
3763*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3764*f9fbec18Smcpowers   mp_sword  w = 0;
3765*f9fbec18Smcpowers #else
3766*f9fbec18Smcpowers   mp_digit  d, diff, borrow = 0;
3767*f9fbec18Smcpowers #endif
3768*f9fbec18Smcpowers 
3769*f9fbec18Smcpowers   /*
3770*f9fbec18Smcpowers     Subtract and propagate borrow.  Up to the precision of b, this
3771*f9fbec18Smcpowers     accounts for the digits of b; after that, we just make sure the
3772*f9fbec18Smcpowers     carries get to the right place.  This saves having to pad b out to
3773*f9fbec18Smcpowers     the precision of a just to make the loops work right...
3774*f9fbec18Smcpowers    */
3775*f9fbec18Smcpowers   pa = MP_DIGITS(a);
3776*f9fbec18Smcpowers   pb = MP_DIGITS(b);
3777*f9fbec18Smcpowers   limit = pb + MP_USED(b);
3778*f9fbec18Smcpowers   while (pb < limit) {
3779*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3780*f9fbec18Smcpowers     w = w + *pa - *pb++;
3781*f9fbec18Smcpowers     *pa++ = ACCUM(w);
3782*f9fbec18Smcpowers     w >>= MP_DIGIT_BIT;
3783*f9fbec18Smcpowers #else
3784*f9fbec18Smcpowers     d = *pa;
3785*f9fbec18Smcpowers     diff = d - *pb++;
3786*f9fbec18Smcpowers     d = (diff > d);				/* detect borrow */
3787*f9fbec18Smcpowers     if (borrow && --diff == MP_DIGIT_MAX)
3788*f9fbec18Smcpowers       ++d;
3789*f9fbec18Smcpowers     *pa++ = diff;
3790*f9fbec18Smcpowers     borrow = d;
3791*f9fbec18Smcpowers #endif
3792*f9fbec18Smcpowers   }
3793*f9fbec18Smcpowers   limit = MP_DIGITS(a) + MP_USED(a);
3794*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3795*f9fbec18Smcpowers   while (w && pa < limit) {
3796*f9fbec18Smcpowers     w = w + *pa;
3797*f9fbec18Smcpowers     *pa++ = ACCUM(w);
3798*f9fbec18Smcpowers     w >>= MP_DIGIT_BIT;
3799*f9fbec18Smcpowers   }
3800*f9fbec18Smcpowers #else
3801*f9fbec18Smcpowers   while (borrow && pa < limit) {
3802*f9fbec18Smcpowers     d = *pa;
3803*f9fbec18Smcpowers     *pa++ = diff = d - borrow;
3804*f9fbec18Smcpowers     borrow = (diff > d);
3805*f9fbec18Smcpowers   }
3806*f9fbec18Smcpowers #endif
3807*f9fbec18Smcpowers 
3808*f9fbec18Smcpowers   /* Clobber any leading zeroes we created    */
3809*f9fbec18Smcpowers   s_mp_clamp(a);
3810*f9fbec18Smcpowers 
3811*f9fbec18Smcpowers   /*
3812*f9fbec18Smcpowers      If there was a borrow out, then |b| > |a| in violation
3813*f9fbec18Smcpowers      of our input invariant.  We've already done the work,
3814*f9fbec18Smcpowers      but we'll at least complain about it...
3815*f9fbec18Smcpowers    */
3816*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3817*f9fbec18Smcpowers   return w ? MP_RANGE : MP_OKAY;
3818*f9fbec18Smcpowers #else
3819*f9fbec18Smcpowers   return borrow ? MP_RANGE : MP_OKAY;
3820*f9fbec18Smcpowers #endif
3821*f9fbec18Smcpowers } /* end s_mp_sub() */
3822*f9fbec18Smcpowers 
3823*f9fbec18Smcpowers /* }}} */
3824*f9fbec18Smcpowers 
3825*f9fbec18Smcpowers /* Compute c = |a| - |b|, assumes |a| >= |b| */ /* magnitude subtract      */
3826*f9fbec18Smcpowers mp_err   s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c)
3827*f9fbec18Smcpowers {
3828*f9fbec18Smcpowers   mp_digit *pa, *pb, *pc;
3829*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3830*f9fbec18Smcpowers   mp_sword  w = 0;
3831*f9fbec18Smcpowers #else
3832*f9fbec18Smcpowers   mp_digit  d, diff, borrow = 0;
3833*f9fbec18Smcpowers #endif
3834*f9fbec18Smcpowers   int       ix, limit;
3835*f9fbec18Smcpowers   mp_err    res;
3836*f9fbec18Smcpowers 
3837*f9fbec18Smcpowers   MP_SIGN(c) = MP_SIGN(a);
3838*f9fbec18Smcpowers 
3839*f9fbec18Smcpowers   /* Make sure a has enough precision for the output value */
3840*f9fbec18Smcpowers   if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a))))
3841*f9fbec18Smcpowers     return res;
3842*f9fbec18Smcpowers 
3843*f9fbec18Smcpowers   /*
3844*f9fbec18Smcpowers     Subtract and propagate borrow.  Up to the precision of b, this
3845*f9fbec18Smcpowers     accounts for the digits of b; after that, we just make sure the
3846*f9fbec18Smcpowers     carries get to the right place.  This saves having to pad b out to
3847*f9fbec18Smcpowers     the precision of a just to make the loops work right...
3848*f9fbec18Smcpowers    */
3849*f9fbec18Smcpowers   pa = MP_DIGITS(a);
3850*f9fbec18Smcpowers   pb = MP_DIGITS(b);
3851*f9fbec18Smcpowers   pc = MP_DIGITS(c);
3852*f9fbec18Smcpowers   limit = MP_USED(b);
3853*f9fbec18Smcpowers   for (ix = 0; ix < limit; ++ix) {
3854*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3855*f9fbec18Smcpowers     w = w + *pa++ - *pb++;
3856*f9fbec18Smcpowers     *pc++ = ACCUM(w);
3857*f9fbec18Smcpowers     w >>= MP_DIGIT_BIT;
3858*f9fbec18Smcpowers #else
3859*f9fbec18Smcpowers     d = *pa++;
3860*f9fbec18Smcpowers     diff = d - *pb++;
3861*f9fbec18Smcpowers     d = (diff > d);
3862*f9fbec18Smcpowers     if (borrow && --diff == MP_DIGIT_MAX)
3863*f9fbec18Smcpowers       ++d;
3864*f9fbec18Smcpowers     *pc++ = diff;
3865*f9fbec18Smcpowers     borrow = d;
3866*f9fbec18Smcpowers #endif
3867*f9fbec18Smcpowers   }
3868*f9fbec18Smcpowers   for (limit = MP_USED(a); ix < limit; ++ix) {
3869*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3870*f9fbec18Smcpowers     w = w + *pa++;
3871*f9fbec18Smcpowers     *pc++ = ACCUM(w);
3872*f9fbec18Smcpowers     w >>= MP_DIGIT_BIT;
3873*f9fbec18Smcpowers #else
3874*f9fbec18Smcpowers     d = *pa++;
3875*f9fbec18Smcpowers     *pc++ = diff = d - borrow;
3876*f9fbec18Smcpowers     borrow = (diff > d);
3877*f9fbec18Smcpowers #endif
3878*f9fbec18Smcpowers   }
3879*f9fbec18Smcpowers 
3880*f9fbec18Smcpowers   /* Clobber any leading zeroes we created    */
3881*f9fbec18Smcpowers   MP_USED(c) = ix;
3882*f9fbec18Smcpowers   s_mp_clamp(c);
3883*f9fbec18Smcpowers 
3884*f9fbec18Smcpowers   /*
3885*f9fbec18Smcpowers      If there was a borrow out, then |b| > |a| in violation
3886*f9fbec18Smcpowers      of our input invariant.  We've already done the work,
3887*f9fbec18Smcpowers      but we'll at least complain about it...
3888*f9fbec18Smcpowers    */
3889*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
3890*f9fbec18Smcpowers   return w ? MP_RANGE : MP_OKAY;
3891*f9fbec18Smcpowers #else
3892*f9fbec18Smcpowers   return borrow ? MP_RANGE : MP_OKAY;
3893*f9fbec18Smcpowers #endif
3894*f9fbec18Smcpowers }
3895*f9fbec18Smcpowers /* {{{ s_mp_mul(a, b) */
3896*f9fbec18Smcpowers 
3897*f9fbec18Smcpowers /* Compute a = |a| * |b|                                                  */
3898*f9fbec18Smcpowers mp_err   s_mp_mul(mp_int *a, const mp_int *b)
3899*f9fbec18Smcpowers {
3900*f9fbec18Smcpowers   return mp_mul(a, b, a);
3901*f9fbec18Smcpowers } /* end s_mp_mul() */
3902*f9fbec18Smcpowers 
3903*f9fbec18Smcpowers /* }}} */
3904*f9fbec18Smcpowers 
3905*f9fbec18Smcpowers #if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY)
3906*f9fbec18Smcpowers /* This trick works on Sparc V8 CPUs with the Workshop compilers. */
3907*f9fbec18Smcpowers #define MP_MUL_DxD(a, b, Phi, Plo) \
3908*f9fbec18Smcpowers   { unsigned long long product = (unsigned long long)a * b; \
3909*f9fbec18Smcpowers     Plo = (mp_digit)product; \
3910*f9fbec18Smcpowers     Phi = (mp_digit)(product >> MP_DIGIT_BIT); }
3911*f9fbec18Smcpowers #elif defined(OSF1)
3912*f9fbec18Smcpowers #define MP_MUL_DxD(a, b, Phi, Plo) \
3913*f9fbec18Smcpowers   { Plo = asm ("mulq %a0, %a1, %v0", a, b);\
3914*f9fbec18Smcpowers     Phi = asm ("umulh %a0, %a1, %v0", a, b); }
3915*f9fbec18Smcpowers #else
3916*f9fbec18Smcpowers #define MP_MUL_DxD(a, b, Phi, Plo) \
3917*f9fbec18Smcpowers   { mp_digit a0b1, a1b0; \
3918*f9fbec18Smcpowers     Plo = (a & MP_HALF_DIGIT_MAX) * (b & MP_HALF_DIGIT_MAX); \
3919*f9fbec18Smcpowers     Phi = (a >> MP_HALF_DIGIT_BIT) * (b >> MP_HALF_DIGIT_BIT); \
3920*f9fbec18Smcpowers     a0b1 = (a & MP_HALF_DIGIT_MAX) * (b >> MP_HALF_DIGIT_BIT); \
3921*f9fbec18Smcpowers     a1b0 = (a >> MP_HALF_DIGIT_BIT) * (b & MP_HALF_DIGIT_MAX); \
3922*f9fbec18Smcpowers     a1b0 += a0b1; \
3923*f9fbec18Smcpowers     Phi += a1b0 >> MP_HALF_DIGIT_BIT; \
3924*f9fbec18Smcpowers     if (a1b0 < a0b1)  \
3925*f9fbec18Smcpowers       Phi += MP_HALF_RADIX; \
3926*f9fbec18Smcpowers     a1b0 <<= MP_HALF_DIGIT_BIT; \
3927*f9fbec18Smcpowers     Plo += a1b0; \
3928*f9fbec18Smcpowers     if (Plo < a1b0) \
3929*f9fbec18Smcpowers       ++Phi; \
3930*f9fbec18Smcpowers   }
3931*f9fbec18Smcpowers #endif
3932*f9fbec18Smcpowers 
3933*f9fbec18Smcpowers #if !defined(MP_ASSEMBLY_MULTIPLY)
3934*f9fbec18Smcpowers /* c = a * b */
3935*f9fbec18Smcpowers void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
3936*f9fbec18Smcpowers {
3937*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
3938*f9fbec18Smcpowers   mp_digit   d = 0;
3939*f9fbec18Smcpowers 
3940*f9fbec18Smcpowers   /* Inner product:  Digits of a */
3941*f9fbec18Smcpowers   while (a_len--) {
3942*f9fbec18Smcpowers     mp_word w = ((mp_word)b * *a++) + d;
3943*f9fbec18Smcpowers     *c++ = ACCUM(w);
3944*f9fbec18Smcpowers     d = CARRYOUT(w);
3945*f9fbec18Smcpowers   }
3946*f9fbec18Smcpowers   *c = d;
3947*f9fbec18Smcpowers #else
3948*f9fbec18Smcpowers   mp_digit carry = 0;
3949*f9fbec18Smcpowers   while (a_len--) {
3950*f9fbec18Smcpowers     mp_digit a_i = *a++;
3951*f9fbec18Smcpowers     mp_digit a0b0, a1b1;
3952*f9fbec18Smcpowers 
3953*f9fbec18Smcpowers     MP_MUL_DxD(a_i, b, a1b1, a0b0);
3954*f9fbec18Smcpowers 
3955*f9fbec18Smcpowers     a0b0 += carry;
3956*f9fbec18Smcpowers     if (a0b0 < carry)
3957*f9fbec18Smcpowers       ++a1b1;
3958*f9fbec18Smcpowers     *c++ = a0b0;
3959*f9fbec18Smcpowers     carry = a1b1;
3960*f9fbec18Smcpowers   }
3961*f9fbec18Smcpowers   *c = carry;
3962*f9fbec18Smcpowers #endif
3963*f9fbec18Smcpowers }
3964*f9fbec18Smcpowers 
3965*f9fbec18Smcpowers /* c += a * b */
3966*f9fbec18Smcpowers void s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b,
3967*f9fbec18Smcpowers 			      mp_digit *c)
3968*f9fbec18Smcpowers {
3969*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
3970*f9fbec18Smcpowers   mp_digit   d = 0;
3971*f9fbec18Smcpowers 
3972*f9fbec18Smcpowers   /* Inner product:  Digits of a */
3973*f9fbec18Smcpowers   while (a_len--) {
3974*f9fbec18Smcpowers     mp_word w = ((mp_word)b * *a++) + *c + d;
3975*f9fbec18Smcpowers     *c++ = ACCUM(w);
3976*f9fbec18Smcpowers     d = CARRYOUT(w);
3977*f9fbec18Smcpowers   }
3978*f9fbec18Smcpowers   *c = d;
3979*f9fbec18Smcpowers #else
3980*f9fbec18Smcpowers   mp_digit carry = 0;
3981*f9fbec18Smcpowers   while (a_len--) {
3982*f9fbec18Smcpowers     mp_digit a_i = *a++;
3983*f9fbec18Smcpowers     mp_digit a0b0, a1b1;
3984*f9fbec18Smcpowers 
3985*f9fbec18Smcpowers     MP_MUL_DxD(a_i, b, a1b1, a0b0);
3986*f9fbec18Smcpowers 
3987*f9fbec18Smcpowers     a0b0 += carry;
3988*f9fbec18Smcpowers     if (a0b0 < carry)
3989*f9fbec18Smcpowers       ++a1b1;
3990*f9fbec18Smcpowers     a0b0 += a_i = *c;
3991*f9fbec18Smcpowers     if (a0b0 < a_i)
3992*f9fbec18Smcpowers       ++a1b1;
3993*f9fbec18Smcpowers     *c++ = a0b0;
3994*f9fbec18Smcpowers     carry = a1b1;
3995*f9fbec18Smcpowers   }
3996*f9fbec18Smcpowers   *c = carry;
3997*f9fbec18Smcpowers #endif
3998*f9fbec18Smcpowers }
3999*f9fbec18Smcpowers 
4000*f9fbec18Smcpowers /* Presently, this is only used by the Montgomery arithmetic code. */
4001*f9fbec18Smcpowers /* c += a * b */
4002*f9fbec18Smcpowers void s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
4003*f9fbec18Smcpowers {
4004*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
4005*f9fbec18Smcpowers   mp_digit   d = 0;
4006*f9fbec18Smcpowers 
4007*f9fbec18Smcpowers   /* Inner product:  Digits of a */
4008*f9fbec18Smcpowers   while (a_len--) {
4009*f9fbec18Smcpowers     mp_word w = ((mp_word)b * *a++) + *c + d;
4010*f9fbec18Smcpowers     *c++ = ACCUM(w);
4011*f9fbec18Smcpowers     d = CARRYOUT(w);
4012*f9fbec18Smcpowers   }
4013*f9fbec18Smcpowers 
4014*f9fbec18Smcpowers   while (d) {
4015*f9fbec18Smcpowers     mp_word w = (mp_word)*c + d;
4016*f9fbec18Smcpowers     *c++ = ACCUM(w);
4017*f9fbec18Smcpowers     d = CARRYOUT(w);
4018*f9fbec18Smcpowers   }
4019*f9fbec18Smcpowers #else
4020*f9fbec18Smcpowers   mp_digit carry = 0;
4021*f9fbec18Smcpowers   while (a_len--) {
4022*f9fbec18Smcpowers     mp_digit a_i = *a++;
4023*f9fbec18Smcpowers     mp_digit a0b0, a1b1;
4024*f9fbec18Smcpowers 
4025*f9fbec18Smcpowers     MP_MUL_DxD(a_i, b, a1b1, a0b0);
4026*f9fbec18Smcpowers 
4027*f9fbec18Smcpowers     a0b0 += carry;
4028*f9fbec18Smcpowers     if (a0b0 < carry)
4029*f9fbec18Smcpowers       ++a1b1;
4030*f9fbec18Smcpowers 
4031*f9fbec18Smcpowers     a0b0 += a_i = *c;
4032*f9fbec18Smcpowers     if (a0b0 < a_i)
4033*f9fbec18Smcpowers       ++a1b1;
4034*f9fbec18Smcpowers 
4035*f9fbec18Smcpowers     *c++ = a0b0;
4036*f9fbec18Smcpowers     carry = a1b1;
4037*f9fbec18Smcpowers   }
4038*f9fbec18Smcpowers   while (carry) {
4039*f9fbec18Smcpowers     mp_digit c_i = *c;
4040*f9fbec18Smcpowers     carry += c_i;
4041*f9fbec18Smcpowers     *c++ = carry;
4042*f9fbec18Smcpowers     carry = carry < c_i;
4043*f9fbec18Smcpowers   }
4044*f9fbec18Smcpowers #endif
4045*f9fbec18Smcpowers }
4046*f9fbec18Smcpowers #endif
4047*f9fbec18Smcpowers 
4048*f9fbec18Smcpowers #if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY)
4049*f9fbec18Smcpowers /* This trick works on Sparc V8 CPUs with the Workshop compilers. */
4050*f9fbec18Smcpowers #define MP_SQR_D(a, Phi, Plo) \
4051*f9fbec18Smcpowers   { unsigned long long square = (unsigned long long)a * a; \
4052*f9fbec18Smcpowers     Plo = (mp_digit)square; \
4053*f9fbec18Smcpowers     Phi = (mp_digit)(square >> MP_DIGIT_BIT); }
4054*f9fbec18Smcpowers #elif defined(OSF1)
4055*f9fbec18Smcpowers #define MP_SQR_D(a, Phi, Plo) \
4056*f9fbec18Smcpowers   { Plo = asm ("mulq  %a0, %a0, %v0", a);\
4057*f9fbec18Smcpowers     Phi = asm ("umulh %a0, %a0, %v0", a); }
4058*f9fbec18Smcpowers #else
4059*f9fbec18Smcpowers #define MP_SQR_D(a, Phi, Plo) \
4060*f9fbec18Smcpowers   { mp_digit Pmid; \
4061*f9fbec18Smcpowers     Plo  = (a  & MP_HALF_DIGIT_MAX) * (a  & MP_HALF_DIGIT_MAX); \
4062*f9fbec18Smcpowers     Phi  = (a >> MP_HALF_DIGIT_BIT) * (a >> MP_HALF_DIGIT_BIT); \
4063*f9fbec18Smcpowers     Pmid = (a  & MP_HALF_DIGIT_MAX) * (a >> MP_HALF_DIGIT_BIT); \
4064*f9fbec18Smcpowers     Phi += Pmid >> (MP_HALF_DIGIT_BIT - 1);  \
4065*f9fbec18Smcpowers     Pmid <<= (MP_HALF_DIGIT_BIT + 1);  \
4066*f9fbec18Smcpowers     Plo += Pmid;  \
4067*f9fbec18Smcpowers     if (Plo < Pmid)  \
4068*f9fbec18Smcpowers       ++Phi;  \
4069*f9fbec18Smcpowers   }
4070*f9fbec18Smcpowers #endif
4071*f9fbec18Smcpowers 
4072*f9fbec18Smcpowers #if !defined(MP_ASSEMBLY_SQUARE)
4073*f9fbec18Smcpowers /* Add the squares of the digits of a to the digits of b. */
4074*f9fbec18Smcpowers void s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
4075*f9fbec18Smcpowers {
4076*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
4077*f9fbec18Smcpowers   mp_word  w;
4078*f9fbec18Smcpowers   mp_digit d;
4079*f9fbec18Smcpowers   mp_size  ix;
4080*f9fbec18Smcpowers 
4081*f9fbec18Smcpowers   w  = 0;
4082*f9fbec18Smcpowers #define ADD_SQUARE(n) \
4083*f9fbec18Smcpowers     d = pa[n]; \
4084*f9fbec18Smcpowers     w += (d * (mp_word)d) + ps[2*n]; \
4085*f9fbec18Smcpowers     ps[2*n] = ACCUM(w); \
4086*f9fbec18Smcpowers     w = (w >> DIGIT_BIT) + ps[2*n+1]; \
4087*f9fbec18Smcpowers     ps[2*n+1] = ACCUM(w); \
4088*f9fbec18Smcpowers     w = (w >> DIGIT_BIT)
4089*f9fbec18Smcpowers 
4090*f9fbec18Smcpowers   for (ix = a_len; ix >= 4; ix -= 4) {
4091*f9fbec18Smcpowers     ADD_SQUARE(0);
4092*f9fbec18Smcpowers     ADD_SQUARE(1);
4093*f9fbec18Smcpowers     ADD_SQUARE(2);
4094*f9fbec18Smcpowers     ADD_SQUARE(3);
4095*f9fbec18Smcpowers     pa += 4;
4096*f9fbec18Smcpowers     ps += 8;
4097*f9fbec18Smcpowers   }
4098*f9fbec18Smcpowers   if (ix) {
4099*f9fbec18Smcpowers     ps += 2*ix;
4100*f9fbec18Smcpowers     pa += ix;
4101*f9fbec18Smcpowers     switch (ix) {
4102*f9fbec18Smcpowers     case 3: ADD_SQUARE(-3); /* FALLTHRU */
4103*f9fbec18Smcpowers     case 2: ADD_SQUARE(-2); /* FALLTHRU */
4104*f9fbec18Smcpowers     case 1: ADD_SQUARE(-1); /* FALLTHRU */
4105*f9fbec18Smcpowers     case 0: break;
4106*f9fbec18Smcpowers     }
4107*f9fbec18Smcpowers   }
4108*f9fbec18Smcpowers   while (w) {
4109*f9fbec18Smcpowers     w += *ps;
4110*f9fbec18Smcpowers     *ps++ = ACCUM(w);
4111*f9fbec18Smcpowers     w = (w >> DIGIT_BIT);
4112*f9fbec18Smcpowers   }
4113*f9fbec18Smcpowers #else
4114*f9fbec18Smcpowers   mp_digit carry = 0;
4115*f9fbec18Smcpowers   while (a_len--) {
4116*f9fbec18Smcpowers     mp_digit a_i = *pa++;
4117*f9fbec18Smcpowers     mp_digit a0a0, a1a1;
4118*f9fbec18Smcpowers 
4119*f9fbec18Smcpowers     MP_SQR_D(a_i, a1a1, a0a0);
4120*f9fbec18Smcpowers 
4121*f9fbec18Smcpowers     /* here a1a1 and a0a0 constitute a_i ** 2 */
4122*f9fbec18Smcpowers     a0a0 += carry;
4123*f9fbec18Smcpowers     if (a0a0 < carry)
4124*f9fbec18Smcpowers       ++a1a1;
4125*f9fbec18Smcpowers 
4126*f9fbec18Smcpowers     /* now add to ps */
4127*f9fbec18Smcpowers     a0a0 += a_i = *ps;
4128*f9fbec18Smcpowers     if (a0a0 < a_i)
4129*f9fbec18Smcpowers       ++a1a1;
4130*f9fbec18Smcpowers     *ps++ = a0a0;
4131*f9fbec18Smcpowers     a1a1 += a_i = *ps;
4132*f9fbec18Smcpowers     carry = (a1a1 < a_i);
4133*f9fbec18Smcpowers     *ps++ = a1a1;
4134*f9fbec18Smcpowers   }
4135*f9fbec18Smcpowers   while (carry) {
4136*f9fbec18Smcpowers     mp_digit s_i = *ps;
4137*f9fbec18Smcpowers     carry += s_i;
4138*f9fbec18Smcpowers     *ps++ = carry;
4139*f9fbec18Smcpowers     carry = carry < s_i;
4140*f9fbec18Smcpowers   }
4141*f9fbec18Smcpowers #endif
4142*f9fbec18Smcpowers }
4143*f9fbec18Smcpowers #endif
4144*f9fbec18Smcpowers 
4145*f9fbec18Smcpowers #if (defined(MP_NO_MP_WORD) || defined(MP_NO_DIV_WORD)) \
4146*f9fbec18Smcpowers && !defined(MP_ASSEMBLY_DIV_2DX1D)
4147*f9fbec18Smcpowers /*
4148*f9fbec18Smcpowers ** Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
4149*f9fbec18Smcpowers ** so its high bit is 1.   This code is from NSPR.
4150*f9fbec18Smcpowers */
4151*f9fbec18Smcpowers mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
4152*f9fbec18Smcpowers 		       mp_digit *qp, mp_digit *rp)
4153*f9fbec18Smcpowers {
4154*f9fbec18Smcpowers     mp_digit d1, d0, q1, q0;
4155*f9fbec18Smcpowers     mp_digit r1, r0, m;
4156*f9fbec18Smcpowers 
4157*f9fbec18Smcpowers     d1 = divisor >> MP_HALF_DIGIT_BIT;
4158*f9fbec18Smcpowers     d0 = divisor & MP_HALF_DIGIT_MAX;
4159*f9fbec18Smcpowers     r1 = Nhi % d1;
4160*f9fbec18Smcpowers     q1 = Nhi / d1;
4161*f9fbec18Smcpowers     m = q1 * d0;
4162*f9fbec18Smcpowers     r1 = (r1 << MP_HALF_DIGIT_BIT) | (Nlo >> MP_HALF_DIGIT_BIT);
4163*f9fbec18Smcpowers     if (r1 < m) {
4164*f9fbec18Smcpowers         q1--, r1 += divisor;
4165*f9fbec18Smcpowers         if (r1 >= divisor && r1 < m) {
4166*f9fbec18Smcpowers 	    q1--, r1 += divisor;
4167*f9fbec18Smcpowers 	}
4168*f9fbec18Smcpowers     }
4169*f9fbec18Smcpowers     r1 -= m;
4170*f9fbec18Smcpowers     r0 = r1 % d1;
4171*f9fbec18Smcpowers     q0 = r1 / d1;
4172*f9fbec18Smcpowers     m = q0 * d0;
4173*f9fbec18Smcpowers     r0 = (r0 << MP_HALF_DIGIT_BIT) | (Nlo & MP_HALF_DIGIT_MAX);
4174*f9fbec18Smcpowers     if (r0 < m) {
4175*f9fbec18Smcpowers         q0--, r0 += divisor;
4176*f9fbec18Smcpowers         if (r0 >= divisor && r0 < m) {
4177*f9fbec18Smcpowers 	    q0--, r0 += divisor;
4178*f9fbec18Smcpowers 	}
4179*f9fbec18Smcpowers     }
4180*f9fbec18Smcpowers     if (qp)
4181*f9fbec18Smcpowers 	*qp = (q1 << MP_HALF_DIGIT_BIT) | q0;
4182*f9fbec18Smcpowers     if (rp)
4183*f9fbec18Smcpowers 	*rp = r0 - m;
4184*f9fbec18Smcpowers     return MP_OKAY;
4185*f9fbec18Smcpowers }
4186*f9fbec18Smcpowers #endif
4187*f9fbec18Smcpowers 
4188*f9fbec18Smcpowers #if MP_SQUARE
4189*f9fbec18Smcpowers /* {{{ s_mp_sqr(a) */
4190*f9fbec18Smcpowers 
4191*f9fbec18Smcpowers mp_err   s_mp_sqr(mp_int *a)
4192*f9fbec18Smcpowers {
4193*f9fbec18Smcpowers   mp_err   res;
4194*f9fbec18Smcpowers   mp_int   tmp;
4195*f9fbec18Smcpowers 
4196*f9fbec18Smcpowers   if((res = mp_init_size(&tmp, 2 * USED(a), FLAG(a))) != MP_OKAY)
4197*f9fbec18Smcpowers     return res;
4198*f9fbec18Smcpowers   res = mp_sqr(a, &tmp);
4199*f9fbec18Smcpowers   if (res == MP_OKAY) {
4200*f9fbec18Smcpowers     s_mp_exch(&tmp, a);
4201*f9fbec18Smcpowers   }
4202*f9fbec18Smcpowers   mp_clear(&tmp);
4203*f9fbec18Smcpowers   return res;
4204*f9fbec18Smcpowers }
4205*f9fbec18Smcpowers 
4206*f9fbec18Smcpowers /* }}} */
4207*f9fbec18Smcpowers #endif
4208*f9fbec18Smcpowers 
4209*f9fbec18Smcpowers /* {{{ s_mp_div(a, b) */
4210*f9fbec18Smcpowers 
4211*f9fbec18Smcpowers /*
4212*f9fbec18Smcpowers   s_mp_div(a, b)
4213*f9fbec18Smcpowers 
4214*f9fbec18Smcpowers   Compute a = a / b and b = a mod b.  Assumes b > a.
4215*f9fbec18Smcpowers  */
4216*f9fbec18Smcpowers 
4217*f9fbec18Smcpowers mp_err   s_mp_div(mp_int *rem, 	/* i: dividend, o: remainder */
4218*f9fbec18Smcpowers                   mp_int *div, 	/* i: divisor                */
4219*f9fbec18Smcpowers 		  mp_int *quot)	/* i: 0;        o: quotient  */
4220*f9fbec18Smcpowers {
4221*f9fbec18Smcpowers   mp_int   part, t;
4222*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
4223*f9fbec18Smcpowers   mp_word  q_msd;
4224*f9fbec18Smcpowers #else
4225*f9fbec18Smcpowers   mp_digit q_msd;
4226*f9fbec18Smcpowers #endif
4227*f9fbec18Smcpowers   mp_err   res;
4228*f9fbec18Smcpowers   mp_digit d;
4229*f9fbec18Smcpowers   mp_digit div_msd;
4230*f9fbec18Smcpowers   int      ix;
4231*f9fbec18Smcpowers 
4232*f9fbec18Smcpowers   if(mp_cmp_z(div) == 0)
4233*f9fbec18Smcpowers     return MP_RANGE;
4234*f9fbec18Smcpowers 
4235*f9fbec18Smcpowers   /* Shortcut if divisor is power of two */
4236*f9fbec18Smcpowers   if((ix = s_mp_ispow2(div)) >= 0) {
4237*f9fbec18Smcpowers     MP_CHECKOK( mp_copy(rem, quot) );
4238*f9fbec18Smcpowers     s_mp_div_2d(quot, (mp_digit)ix);
4239*f9fbec18Smcpowers     s_mp_mod_2d(rem,  (mp_digit)ix);
4240*f9fbec18Smcpowers 
4241*f9fbec18Smcpowers     return MP_OKAY;
4242*f9fbec18Smcpowers   }
4243*f9fbec18Smcpowers 
4244*f9fbec18Smcpowers   DIGITS(&t) = 0;
4245*f9fbec18Smcpowers   MP_SIGN(rem) = ZPOS;
4246*f9fbec18Smcpowers   MP_SIGN(div) = ZPOS;
4247*f9fbec18Smcpowers 
4248*f9fbec18Smcpowers   /* A working temporary for division     */
4249*f9fbec18Smcpowers   MP_CHECKOK( mp_init_size(&t, MP_ALLOC(rem), FLAG(rem)));
4250*f9fbec18Smcpowers 
4251*f9fbec18Smcpowers   /* Normalize to optimize guessing       */
4252*f9fbec18Smcpowers   MP_CHECKOK( s_mp_norm(rem, div, &d) );
4253*f9fbec18Smcpowers 
4254*f9fbec18Smcpowers   part = *rem;
4255*f9fbec18Smcpowers 
4256*f9fbec18Smcpowers   /* Perform the division itself...woo!   */
4257*f9fbec18Smcpowers   MP_USED(quot) = MP_ALLOC(quot);
4258*f9fbec18Smcpowers 
4259*f9fbec18Smcpowers   /* Find a partial substring of rem which is at least div */
4260*f9fbec18Smcpowers   /* If we didn't find one, we're finished dividing    */
4261*f9fbec18Smcpowers   while (MP_USED(rem) > MP_USED(div) || s_mp_cmp(rem, div) >= 0) {
4262*f9fbec18Smcpowers     int i;
4263*f9fbec18Smcpowers     int unusedRem;
4264*f9fbec18Smcpowers 
4265*f9fbec18Smcpowers     unusedRem = MP_USED(rem) - MP_USED(div);
4266*f9fbec18Smcpowers     MP_DIGITS(&part) = MP_DIGITS(rem) + unusedRem;
4267*f9fbec18Smcpowers     MP_ALLOC(&part)  = MP_ALLOC(rem)  - unusedRem;
4268*f9fbec18Smcpowers     MP_USED(&part)   = MP_USED(div);
4269*f9fbec18Smcpowers     if (s_mp_cmp(&part, div) < 0) {
4270*f9fbec18Smcpowers       -- unusedRem;
4271*f9fbec18Smcpowers #if MP_ARGCHK == 2
4272*f9fbec18Smcpowers       assert(unusedRem >= 0);
4273*f9fbec18Smcpowers #endif
4274*f9fbec18Smcpowers       -- MP_DIGITS(&part);
4275*f9fbec18Smcpowers       ++ MP_USED(&part);
4276*f9fbec18Smcpowers       ++ MP_ALLOC(&part);
4277*f9fbec18Smcpowers     }
4278*f9fbec18Smcpowers 
4279*f9fbec18Smcpowers     /* Compute a guess for the next quotient digit       */
4280*f9fbec18Smcpowers     q_msd = MP_DIGIT(&part, MP_USED(&part) - 1);
4281*f9fbec18Smcpowers     div_msd = MP_DIGIT(div, MP_USED(div) - 1);
4282*f9fbec18Smcpowers     if (q_msd >= div_msd) {
4283*f9fbec18Smcpowers       q_msd = 1;
4284*f9fbec18Smcpowers     } else if (MP_USED(&part) > 1) {
4285*f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
4286*f9fbec18Smcpowers       q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2);
4287*f9fbec18Smcpowers       q_msd /= div_msd;
4288*f9fbec18Smcpowers       if (q_msd == RADIX)
4289*f9fbec18Smcpowers         --q_msd;
4290*f9fbec18Smcpowers #else
4291*f9fbec18Smcpowers       mp_digit r;
4292*f9fbec18Smcpowers       MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2),
4293*f9fbec18Smcpowers 				  div_msd, &q_msd, &r) );
4294*f9fbec18Smcpowers #endif
4295*f9fbec18Smcpowers     } else {
4296*f9fbec18Smcpowers       q_msd = 0;
4297*f9fbec18Smcpowers     }
4298*f9fbec18Smcpowers #if MP_ARGCHK == 2
4299*f9fbec18Smcpowers     assert(q_msd > 0); /* This case should never occur any more. */
4300*f9fbec18Smcpowers #endif
4301*f9fbec18Smcpowers     if (q_msd <= 0)
4302*f9fbec18Smcpowers       break;
4303*f9fbec18Smcpowers 
4304*f9fbec18Smcpowers     /* See what that multiplies out to                   */
4305*f9fbec18Smcpowers     mp_copy(div, &t);
4306*f9fbec18Smcpowers     MP_CHECKOK( s_mp_mul_d(&t, (mp_digit)q_msd) );
4307*f9fbec18Smcpowers 
4308*f9fbec18Smcpowers     /*
4309*f9fbec18Smcpowers        If it's too big, back it off.  We should not have to do this
4310*f9fbec18Smcpowers        more than once, or, in rare cases, twice.  Knuth describes a
4311*f9fbec18Smcpowers        method by which this could be reduced to a maximum of once, but
4312*f9fbec18Smcpowers        I didn't implement that here.
4313*f9fbec18Smcpowers      * When using s_mpv_div_2dx1d, we may have to do this 3 times.
4314*f9fbec18Smcpowers      */
4315*f9fbec18Smcpowers     for (i = 4; s_mp_cmp(&t, &part) > 0 && i > 0; --i) {
4316*f9fbec18Smcpowers       --q_msd;
4317*f9fbec18Smcpowers       s_mp_sub(&t, div);	/* t -= div */
4318*f9fbec18Smcpowers     }
4319*f9fbec18Smcpowers     if (i < 0) {
4320*f9fbec18Smcpowers       res = MP_RANGE;
4321*f9fbec18Smcpowers       goto CLEANUP;
4322*f9fbec18Smcpowers     }
4323*f9fbec18Smcpowers 
4324*f9fbec18Smcpowers     /* At this point, q_msd should be the right next digit   */
4325*f9fbec18Smcpowers     MP_CHECKOK( s_mp_sub(&part, &t) );	/* part -= t */
4326*f9fbec18Smcpowers     s_mp_clamp(rem);
4327*f9fbec18Smcpowers 
4328*f9fbec18Smcpowers     /*
4329*f9fbec18Smcpowers       Include the digit in the quotient.  We allocated enough memory
4330*f9fbec18Smcpowers       for any quotient we could ever possibly get, so we should not
4331*f9fbec18Smcpowers       have to check for failures here
4332*f9fbec18Smcpowers      */
4333*f9fbec18Smcpowers     MP_DIGIT(quot, unusedRem) = (mp_digit)q_msd;
4334*f9fbec18Smcpowers   }
4335*f9fbec18Smcpowers 
4336*f9fbec18Smcpowers   /* Denormalize remainder                */
4337*f9fbec18Smcpowers   if (d) {
4338*f9fbec18Smcpowers     s_mp_div_2d(rem, d);
4339*f9fbec18Smcpowers   }
4340*f9fbec18Smcpowers 
4341*f9fbec18Smcpowers   s_mp_clamp(quot);
4342*f9fbec18Smcpowers 
4343*f9fbec18Smcpowers CLEANUP:
4344*f9fbec18Smcpowers   mp_clear(&t);
4345*f9fbec18Smcpowers 
4346*f9fbec18Smcpowers   return res;
4347*f9fbec18Smcpowers 
4348*f9fbec18Smcpowers } /* end s_mp_div() */
4349*f9fbec18Smcpowers 
4350*f9fbec18Smcpowers 
4351*f9fbec18Smcpowers /* }}} */
4352*f9fbec18Smcpowers 
4353*f9fbec18Smcpowers /* {{{ s_mp_2expt(a, k) */
4354*f9fbec18Smcpowers 
4355*f9fbec18Smcpowers mp_err   s_mp_2expt(mp_int *a, mp_digit k)
4356*f9fbec18Smcpowers {
4357*f9fbec18Smcpowers   mp_err    res;
4358*f9fbec18Smcpowers   mp_size   dig, bit;
4359*f9fbec18Smcpowers 
4360*f9fbec18Smcpowers   dig = k / DIGIT_BIT;
4361*f9fbec18Smcpowers   bit = k % DIGIT_BIT;
4362*f9fbec18Smcpowers 
4363*f9fbec18Smcpowers   mp_zero(a);
4364*f9fbec18Smcpowers   if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
4365*f9fbec18Smcpowers     return res;
4366*f9fbec18Smcpowers 
4367*f9fbec18Smcpowers   DIGIT(a, dig) |= ((mp_digit)1 << bit);
4368*f9fbec18Smcpowers 
4369*f9fbec18Smcpowers   return MP_OKAY;
4370*f9fbec18Smcpowers 
4371*f9fbec18Smcpowers } /* end s_mp_2expt() */
4372*f9fbec18Smcpowers 
4373*f9fbec18Smcpowers /* }}} */
4374*f9fbec18Smcpowers 
4375*f9fbec18Smcpowers /* {{{ s_mp_reduce(x, m, mu) */
4376*f9fbec18Smcpowers 
4377*f9fbec18Smcpowers /*
4378*f9fbec18Smcpowers   Compute Barrett reduction, x (mod m), given a precomputed value for
4379*f9fbec18Smcpowers   mu = b^2k / m, where b = RADIX and k = #digits(m).  This should be
4380*f9fbec18Smcpowers   faster than straight division, when many reductions by the same
4381*f9fbec18Smcpowers   value of m are required (such as in modular exponentiation).  This
4382*f9fbec18Smcpowers   can nearly halve the time required to do modular exponentiation,
4383*f9fbec18Smcpowers   as compared to using the full integer divide to reduce.
4384*f9fbec18Smcpowers 
4385*f9fbec18Smcpowers   This algorithm was derived from the _Handbook of Applied
4386*f9fbec18Smcpowers   Cryptography_ by Menezes, Oorschot and VanStone, Ch. 14,
4387*f9fbec18Smcpowers   pp. 603-604.
4388*f9fbec18Smcpowers  */
4389*f9fbec18Smcpowers 
4390*f9fbec18Smcpowers mp_err   s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu)
4391*f9fbec18Smcpowers {
4392*f9fbec18Smcpowers   mp_int   q;
4393*f9fbec18Smcpowers   mp_err   res;
4394*f9fbec18Smcpowers 
4395*f9fbec18Smcpowers   if((res = mp_init_copy(&q, x)) != MP_OKAY)
4396*f9fbec18Smcpowers     return res;
4397*f9fbec18Smcpowers 
4398*f9fbec18Smcpowers   s_mp_rshd(&q, USED(m) - 1);  /* q1 = x / b^(k-1)  */
4399*f9fbec18Smcpowers   s_mp_mul(&q, mu);            /* q2 = q1 * mu      */
4400*f9fbec18Smcpowers   s_mp_rshd(&q, USED(m) + 1);  /* q3 = q2 / b^(k+1) */
4401*f9fbec18Smcpowers 
4402*f9fbec18Smcpowers   /* x = x mod b^(k+1), quick (no division) */
4403*f9fbec18Smcpowers   s_mp_mod_2d(x, DIGIT_BIT * (USED(m) + 1));
4404*f9fbec18Smcpowers 
4405*f9fbec18Smcpowers   /* q = q * m mod b^(k+1), quick (no division) */
4406*f9fbec18Smcpowers   s_mp_mul(&q, m);
4407*f9fbec18Smcpowers   s_mp_mod_2d(&q, DIGIT_BIT * (USED(m) + 1));
4408*f9fbec18Smcpowers 
4409*f9fbec18Smcpowers   /* x = x - q */
4410*f9fbec18Smcpowers   if((res = mp_sub(x, &q, x)) != MP_OKAY)
4411*f9fbec18Smcpowers     goto CLEANUP;
4412*f9fbec18Smcpowers 
4413*f9fbec18Smcpowers   /* If x < 0, add b^(k+1) to it */
4414*f9fbec18Smcpowers   if(mp_cmp_z(x) < 0) {
4415*f9fbec18Smcpowers     mp_set(&q, 1);
4416*f9fbec18Smcpowers     if((res = s_mp_lshd(&q, USED(m) + 1)) != MP_OKAY)
4417*f9fbec18Smcpowers       goto CLEANUP;
4418*f9fbec18Smcpowers     if((res = mp_add(x, &q, x)) != MP_OKAY)
4419*f9fbec18Smcpowers       goto CLEANUP;
4420*f9fbec18Smcpowers   }
4421*f9fbec18Smcpowers 
4422*f9fbec18Smcpowers   /* Back off if it's too big */
4423*f9fbec18Smcpowers   while(mp_cmp(x, m) >= 0) {
4424*f9fbec18Smcpowers     if((res = s_mp_sub(x, m)) != MP_OKAY)
4425*f9fbec18Smcpowers       break;
4426*f9fbec18Smcpowers   }
4427*f9fbec18Smcpowers 
4428*f9fbec18Smcpowers  CLEANUP:
4429*f9fbec18Smcpowers   mp_clear(&q);
4430*f9fbec18Smcpowers 
4431*f9fbec18Smcpowers   return res;
4432*f9fbec18Smcpowers 
4433*f9fbec18Smcpowers } /* end s_mp_reduce() */
4434*f9fbec18Smcpowers 
4435*f9fbec18Smcpowers /* }}} */
4436*f9fbec18Smcpowers 
4437*f9fbec18Smcpowers /* }}} */
4438*f9fbec18Smcpowers 
4439*f9fbec18Smcpowers /* {{{ Primitive comparisons */
4440*f9fbec18Smcpowers 
4441*f9fbec18Smcpowers /* {{{ s_mp_cmp(a, b) */
4442*f9fbec18Smcpowers 
4443*f9fbec18Smcpowers /* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b           */
4444*f9fbec18Smcpowers int      s_mp_cmp(const mp_int *a, const mp_int *b)
4445*f9fbec18Smcpowers {
4446*f9fbec18Smcpowers   mp_size used_a = MP_USED(a);
4447*f9fbec18Smcpowers   {
4448*f9fbec18Smcpowers     mp_size used_b = MP_USED(b);
4449*f9fbec18Smcpowers 
4450*f9fbec18Smcpowers     if (used_a > used_b)
4451*f9fbec18Smcpowers       goto IS_GT;
4452*f9fbec18Smcpowers     if (used_a < used_b)
4453*f9fbec18Smcpowers       goto IS_LT;
4454*f9fbec18Smcpowers   }
4455*f9fbec18Smcpowers   {
4456*f9fbec18Smcpowers     mp_digit *pa, *pb;
4457*f9fbec18Smcpowers     mp_digit da = 0, db = 0;
4458*f9fbec18Smcpowers 
4459*f9fbec18Smcpowers #define CMP_AB(n) if ((da = pa[n]) != (db = pb[n])) goto done
4460*f9fbec18Smcpowers 
4461*f9fbec18Smcpowers     pa = MP_DIGITS(a) + used_a;
4462*f9fbec18Smcpowers     pb = MP_DIGITS(b) + used_a;
4463*f9fbec18Smcpowers     while (used_a >= 4) {
4464*f9fbec18Smcpowers       pa     -= 4;
4465*f9fbec18Smcpowers       pb     -= 4;
4466*f9fbec18Smcpowers       used_a -= 4;
4467*f9fbec18Smcpowers       CMP_AB(3);
4468*f9fbec18Smcpowers       CMP_AB(2);
4469*f9fbec18Smcpowers       CMP_AB(1);
4470*f9fbec18Smcpowers       CMP_AB(0);
4471*f9fbec18Smcpowers     }
4472*f9fbec18Smcpowers     while (used_a-- > 0 && ((da = *--pa) == (db = *--pb)))
4473*f9fbec18Smcpowers       /* do nothing */;
4474*f9fbec18Smcpowers done:
4475*f9fbec18Smcpowers     if (da > db)
4476*f9fbec18Smcpowers       goto IS_GT;
4477*f9fbec18Smcpowers     if (da < db)
4478*f9fbec18Smcpowers       goto IS_LT;
4479*f9fbec18Smcpowers   }
4480*f9fbec18Smcpowers   return MP_EQ;
4481*f9fbec18Smcpowers IS_LT:
4482*f9fbec18Smcpowers   return MP_LT;
4483*f9fbec18Smcpowers IS_GT:
4484*f9fbec18Smcpowers   return MP_GT;
4485*f9fbec18Smcpowers } /* end s_mp_cmp() */
4486*f9fbec18Smcpowers 
4487*f9fbec18Smcpowers /* }}} */
4488*f9fbec18Smcpowers 
4489*f9fbec18Smcpowers /* {{{ s_mp_cmp_d(a, d) */
4490*f9fbec18Smcpowers 
4491*f9fbec18Smcpowers /* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d             */
4492*f9fbec18Smcpowers int      s_mp_cmp_d(const mp_int *a, mp_digit d)
4493*f9fbec18Smcpowers {
4494*f9fbec18Smcpowers   if(USED(a) > 1)
4495*f9fbec18Smcpowers     return MP_GT;
4496*f9fbec18Smcpowers 
4497*f9fbec18Smcpowers   if(DIGIT(a, 0) < d)
4498*f9fbec18Smcpowers     return MP_LT;
4499*f9fbec18Smcpowers   else if(DIGIT(a, 0) > d)
4500*f9fbec18Smcpowers     return MP_GT;
4501*f9fbec18Smcpowers   else
4502*f9fbec18Smcpowers     return MP_EQ;
4503*f9fbec18Smcpowers 
4504*f9fbec18Smcpowers } /* end s_mp_cmp_d() */
4505*f9fbec18Smcpowers 
4506*f9fbec18Smcpowers /* }}} */
4507*f9fbec18Smcpowers 
4508*f9fbec18Smcpowers /* {{{ s_mp_ispow2(v) */
4509*f9fbec18Smcpowers 
4510*f9fbec18Smcpowers /*
4511*f9fbec18Smcpowers   Returns -1 if the value is not a power of two; otherwise, it returns
4512*f9fbec18Smcpowers   k such that v = 2^k, i.e. lg(v).
4513*f9fbec18Smcpowers  */
4514*f9fbec18Smcpowers int      s_mp_ispow2(const mp_int *v)
4515*f9fbec18Smcpowers {
4516*f9fbec18Smcpowers   mp_digit d;
4517*f9fbec18Smcpowers   int      extra = 0, ix;
4518*f9fbec18Smcpowers 
4519*f9fbec18Smcpowers   ix = MP_USED(v) - 1;
4520*f9fbec18Smcpowers   d = MP_DIGIT(v, ix); /* most significant digit of v */
4521*f9fbec18Smcpowers 
4522*f9fbec18Smcpowers   extra = s_mp_ispow2d(d);
4523*f9fbec18Smcpowers   if (extra < 0 || ix == 0)
4524*f9fbec18Smcpowers     return extra;
4525*f9fbec18Smcpowers 
4526*f9fbec18Smcpowers   while (--ix >= 0) {
4527*f9fbec18Smcpowers     if (DIGIT(v, ix) != 0)
4528*f9fbec18Smcpowers       return -1; /* not a power of two */
4529*f9fbec18Smcpowers     extra += MP_DIGIT_BIT;
4530*f9fbec18Smcpowers   }
4531*f9fbec18Smcpowers 
4532*f9fbec18Smcpowers   return extra;
4533*f9fbec18Smcpowers 
4534*f9fbec18Smcpowers } /* end s_mp_ispow2() */
4535*f9fbec18Smcpowers 
4536*f9fbec18Smcpowers /* }}} */
4537*f9fbec18Smcpowers 
4538*f9fbec18Smcpowers /* {{{ s_mp_ispow2d(d) */
4539*f9fbec18Smcpowers 
4540*f9fbec18Smcpowers int      s_mp_ispow2d(mp_digit d)
4541*f9fbec18Smcpowers {
4542*f9fbec18Smcpowers   if ((d != 0) && ((d & (d-1)) == 0)) { /* d is a power of 2 */
4543*f9fbec18Smcpowers     int pow = 0;
4544*f9fbec18Smcpowers #if defined (MP_USE_UINT_DIGIT)
4545*f9fbec18Smcpowers     if (d & 0xffff0000U)
4546*f9fbec18Smcpowers       pow += 16;
4547*f9fbec18Smcpowers     if (d & 0xff00ff00U)
4548*f9fbec18Smcpowers       pow += 8;
4549*f9fbec18Smcpowers     if (d & 0xf0f0f0f0U)
4550*f9fbec18Smcpowers       pow += 4;
4551*f9fbec18Smcpowers     if (d & 0xccccccccU)
4552*f9fbec18Smcpowers       pow += 2;
4553*f9fbec18Smcpowers     if (d & 0xaaaaaaaaU)
4554*f9fbec18Smcpowers       pow += 1;
4555*f9fbec18Smcpowers #elif defined(MP_USE_LONG_LONG_DIGIT)
4556*f9fbec18Smcpowers     if (d & 0xffffffff00000000ULL)
4557*f9fbec18Smcpowers       pow += 32;
4558*f9fbec18Smcpowers     if (d & 0xffff0000ffff0000ULL)
4559*f9fbec18Smcpowers       pow += 16;
4560*f9fbec18Smcpowers     if (d & 0xff00ff00ff00ff00ULL)
4561*f9fbec18Smcpowers       pow += 8;
4562*f9fbec18Smcpowers     if (d & 0xf0f0f0f0f0f0f0f0ULL)
4563*f9fbec18Smcpowers       pow += 4;
4564*f9fbec18Smcpowers     if (d & 0xccccccccccccccccULL)
4565*f9fbec18Smcpowers       pow += 2;
4566*f9fbec18Smcpowers     if (d & 0xaaaaaaaaaaaaaaaaULL)
4567*f9fbec18Smcpowers       pow += 1;
4568*f9fbec18Smcpowers #elif defined(MP_USE_LONG_DIGIT)
4569*f9fbec18Smcpowers     if (d & 0xffffffff00000000UL)
4570*f9fbec18Smcpowers       pow += 32;
4571*f9fbec18Smcpowers     if (d & 0xffff0000ffff0000UL)
4572*f9fbec18Smcpowers       pow += 16;
4573*f9fbec18Smcpowers     if (d & 0xff00ff00ff00ff00UL)
4574*f9fbec18Smcpowers       pow += 8;
4575*f9fbec18Smcpowers     if (d & 0xf0f0f0f0f0f0f0f0UL)
4576*f9fbec18Smcpowers       pow += 4;
4577*f9fbec18Smcpowers     if (d & 0xccccccccccccccccUL)
4578*f9fbec18Smcpowers       pow += 2;
4579*f9fbec18Smcpowers     if (d & 0xaaaaaaaaaaaaaaaaUL)
4580*f9fbec18Smcpowers       pow += 1;
4581*f9fbec18Smcpowers #else
4582*f9fbec18Smcpowers #error "unknown type for mp_digit"
4583*f9fbec18Smcpowers #endif
4584*f9fbec18Smcpowers     return pow;
4585*f9fbec18Smcpowers   }
4586*f9fbec18Smcpowers   return -1;
4587*f9fbec18Smcpowers 
4588*f9fbec18Smcpowers } /* end s_mp_ispow2d() */
4589*f9fbec18Smcpowers 
4590*f9fbec18Smcpowers /* }}} */
4591*f9fbec18Smcpowers 
4592*f9fbec18Smcpowers /* }}} */
4593*f9fbec18Smcpowers 
4594*f9fbec18Smcpowers /* {{{ Primitive I/O helpers */
4595*f9fbec18Smcpowers 
4596*f9fbec18Smcpowers /* {{{ s_mp_tovalue(ch, r) */
4597*f9fbec18Smcpowers 
4598*f9fbec18Smcpowers /*
4599*f9fbec18Smcpowers   Convert the given character to its digit value, in the given radix.
4600*f9fbec18Smcpowers   If the given character is not understood in the given radix, -1 is
4601*f9fbec18Smcpowers   returned.  Otherwise the digit's numeric value is returned.
4602*f9fbec18Smcpowers 
4603*f9fbec18Smcpowers   The results will be odd if you use a radix < 2 or > 62, you are
4604*f9fbec18Smcpowers   expected to know what you're up to.
4605*f9fbec18Smcpowers  */
4606*f9fbec18Smcpowers int      s_mp_tovalue(char ch, int r)
4607*f9fbec18Smcpowers {
4608*f9fbec18Smcpowers   int    val, xch;
4609*f9fbec18Smcpowers 
4610*f9fbec18Smcpowers   if(r > 36)
4611*f9fbec18Smcpowers     xch = ch;
4612*f9fbec18Smcpowers   else
4613*f9fbec18Smcpowers     xch = toupper(ch);
4614*f9fbec18Smcpowers 
4615*f9fbec18Smcpowers   if(isdigit(xch))
4616*f9fbec18Smcpowers     val = xch - '0';
4617*f9fbec18Smcpowers   else if(isupper(xch))
4618*f9fbec18Smcpowers     val = xch - 'A' + 10;
4619*f9fbec18Smcpowers   else if(islower(xch))
4620*f9fbec18Smcpowers     val = xch - 'a' + 36;
4621*f9fbec18Smcpowers   else if(xch == '+')
4622*f9fbec18Smcpowers     val = 62;
4623*f9fbec18Smcpowers   else if(xch == '/')
4624*f9fbec18Smcpowers     val = 63;
4625*f9fbec18Smcpowers   else
4626*f9fbec18Smcpowers     return -1;
4627*f9fbec18Smcpowers 
4628*f9fbec18Smcpowers   if(val < 0 || val >= r)
4629*f9fbec18Smcpowers     return -1;
4630*f9fbec18Smcpowers 
4631*f9fbec18Smcpowers   return val;
4632*f9fbec18Smcpowers 
4633*f9fbec18Smcpowers } /* end s_mp_tovalue() */
4634*f9fbec18Smcpowers 
4635*f9fbec18Smcpowers /* }}} */
4636*f9fbec18Smcpowers 
4637*f9fbec18Smcpowers /* {{{ s_mp_todigit(val, r, low) */
4638*f9fbec18Smcpowers 
4639*f9fbec18Smcpowers /*
4640*f9fbec18Smcpowers   Convert val to a radix-r digit, if possible.  If val is out of range
4641*f9fbec18Smcpowers   for r, returns zero.  Otherwise, returns an ASCII character denoting
4642*f9fbec18Smcpowers   the value in the given radix.
4643*f9fbec18Smcpowers 
4644*f9fbec18Smcpowers   The results may be odd if you use a radix < 2 or > 64, you are
4645*f9fbec18Smcpowers   expected to know what you're doing.
4646*f9fbec18Smcpowers  */
4647*f9fbec18Smcpowers 
4648*f9fbec18Smcpowers char     s_mp_todigit(mp_digit val, int r, int low)
4649*f9fbec18Smcpowers {
4650*f9fbec18Smcpowers   char   ch;
4651*f9fbec18Smcpowers 
4652*f9fbec18Smcpowers   if(val >= r)
4653*f9fbec18Smcpowers     return 0;
4654*f9fbec18Smcpowers 
4655*f9fbec18Smcpowers   ch = s_dmap_1[val];
4656*f9fbec18Smcpowers 
4657*f9fbec18Smcpowers   if(r <= 36 && low)
4658*f9fbec18Smcpowers     ch = tolower(ch);
4659*f9fbec18Smcpowers 
4660*f9fbec18Smcpowers   return ch;
4661*f9fbec18Smcpowers 
4662*f9fbec18Smcpowers } /* end s_mp_todigit() */
4663*f9fbec18Smcpowers 
4664*f9fbec18Smcpowers /* }}} */
4665*f9fbec18Smcpowers 
4666*f9fbec18Smcpowers /* {{{ s_mp_outlen(bits, radix) */
4667*f9fbec18Smcpowers 
4668*f9fbec18Smcpowers /*
4669*f9fbec18Smcpowers    Return an estimate for how long a string is needed to hold a radix
4670*f9fbec18Smcpowers    r representation of a number with 'bits' significant bits, plus an
4671*f9fbec18Smcpowers    extra for a zero terminator (assuming C style strings here)
4672*f9fbec18Smcpowers  */
4673*f9fbec18Smcpowers int      s_mp_outlen(int bits, int r)
4674*f9fbec18Smcpowers {
4675*f9fbec18Smcpowers   return (int)((double)bits * LOG_V_2(r) + 1.5) + 1;
4676*f9fbec18Smcpowers 
4677*f9fbec18Smcpowers } /* end s_mp_outlen() */
4678*f9fbec18Smcpowers 
4679*f9fbec18Smcpowers /* }}} */
4680*f9fbec18Smcpowers 
4681*f9fbec18Smcpowers /* }}} */
4682*f9fbec18Smcpowers 
4683*f9fbec18Smcpowers /* {{{ mp_read_unsigned_octets(mp, str, len) */
4684*f9fbec18Smcpowers /* mp_read_unsigned_octets(mp, str, len)
4685*f9fbec18Smcpowers    Read in a raw value (base 256) into the given mp_int
4686*f9fbec18Smcpowers    No sign bit, number is positive.  Leading zeros ignored.
4687*f9fbec18Smcpowers  */
4688*f9fbec18Smcpowers 
4689*f9fbec18Smcpowers mp_err
4690*f9fbec18Smcpowers mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len)
4691*f9fbec18Smcpowers {
4692*f9fbec18Smcpowers   int            count;
4693*f9fbec18Smcpowers   mp_err         res;
4694*f9fbec18Smcpowers   mp_digit       d;
4695*f9fbec18Smcpowers 
4696*f9fbec18Smcpowers   ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
4697*f9fbec18Smcpowers 
4698*f9fbec18Smcpowers   mp_zero(mp);
4699*f9fbec18Smcpowers 
4700*f9fbec18Smcpowers   count = len % sizeof(mp_digit);
4701*f9fbec18Smcpowers   if (count) {
4702*f9fbec18Smcpowers     for (d = 0; count-- > 0; --len) {
4703*f9fbec18Smcpowers       d = (d << 8) | *str++;
4704*f9fbec18Smcpowers     }
4705*f9fbec18Smcpowers     MP_DIGIT(mp, 0) = d;
4706*f9fbec18Smcpowers   }
4707*f9fbec18Smcpowers 
4708*f9fbec18Smcpowers   /* Read the rest of the digits */
4709*f9fbec18Smcpowers   for(; len > 0; len -= sizeof(mp_digit)) {
4710*f9fbec18Smcpowers     for (d = 0, count = sizeof(mp_digit); count > 0; --count) {
4711*f9fbec18Smcpowers       d = (d << 8) | *str++;
4712*f9fbec18Smcpowers     }
4713*f9fbec18Smcpowers     if (MP_EQ == mp_cmp_z(mp)) {
4714*f9fbec18Smcpowers       if (!d)
4715*f9fbec18Smcpowers 	continue;
4716*f9fbec18Smcpowers     } else {
4717*f9fbec18Smcpowers       if((res = s_mp_lshd(mp, 1)) != MP_OKAY)
4718*f9fbec18Smcpowers 	return res;
4719*f9fbec18Smcpowers     }
4720*f9fbec18Smcpowers     MP_DIGIT(mp, 0) = d;
4721*f9fbec18Smcpowers   }
4722*f9fbec18Smcpowers   return MP_OKAY;
4723*f9fbec18Smcpowers } /* end mp_read_unsigned_octets() */
4724*f9fbec18Smcpowers /* }}} */
4725*f9fbec18Smcpowers 
4726*f9fbec18Smcpowers /* {{{ mp_unsigned_octet_size(mp) */
4727*f9fbec18Smcpowers int
4728*f9fbec18Smcpowers mp_unsigned_octet_size(const mp_int *mp)
4729*f9fbec18Smcpowers {
4730*f9fbec18Smcpowers   int  bytes;
4731*f9fbec18Smcpowers   int  ix;
4732*f9fbec18Smcpowers   mp_digit  d = 0;
4733*f9fbec18Smcpowers 
4734*f9fbec18Smcpowers   ARGCHK(mp != NULL, MP_BADARG);
4735*f9fbec18Smcpowers   ARGCHK(MP_ZPOS == SIGN(mp), MP_BADARG);
4736*f9fbec18Smcpowers 
4737*f9fbec18Smcpowers   bytes = (USED(mp) * sizeof(mp_digit));
4738*f9fbec18Smcpowers 
4739*f9fbec18Smcpowers   /* subtract leading zeros. */
4740*f9fbec18Smcpowers   /* Iterate over each digit... */
4741*f9fbec18Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
4742*f9fbec18Smcpowers     d = DIGIT(mp, ix);
4743*f9fbec18Smcpowers     if (d)
4744*f9fbec18Smcpowers 	break;
4745*f9fbec18Smcpowers     bytes -= sizeof(d);
4746*f9fbec18Smcpowers   }
4747*f9fbec18Smcpowers   if (!bytes)
4748*f9fbec18Smcpowers     return 1;
4749*f9fbec18Smcpowers 
4750*f9fbec18Smcpowers   /* Have MSD, check digit bytes, high order first */
4751*f9fbec18Smcpowers   for(ix = sizeof(mp_digit) - 1; ix >= 0; ix--) {
4752*f9fbec18Smcpowers     unsigned char x = (unsigned char)(d >> (ix * CHAR_BIT));
4753*f9fbec18Smcpowers     if (x)
4754*f9fbec18Smcpowers 	break;
4755*f9fbec18Smcpowers     --bytes;
4756*f9fbec18Smcpowers   }
4757*f9fbec18Smcpowers   return bytes;
4758*f9fbec18Smcpowers } /* end mp_unsigned_octet_size() */
4759*f9fbec18Smcpowers /* }}} */
4760*f9fbec18Smcpowers 
4761*f9fbec18Smcpowers /* {{{ mp_to_unsigned_octets(mp, str) */
4762*f9fbec18Smcpowers /* output a buffer of big endian octets no longer than specified. */
4763*f9fbec18Smcpowers mp_err
4764*f9fbec18Smcpowers mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
4765*f9fbec18Smcpowers {
4766*f9fbec18Smcpowers   int  ix, pos = 0;
4767*f9fbec18Smcpowers   int  bytes;
4768*f9fbec18Smcpowers 
4769*f9fbec18Smcpowers   ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
4770*f9fbec18Smcpowers 
4771*f9fbec18Smcpowers   bytes = mp_unsigned_octet_size(mp);
4772*f9fbec18Smcpowers   ARGCHK(bytes <= maxlen, MP_BADARG);
4773*f9fbec18Smcpowers 
4774*f9fbec18Smcpowers   /* Iterate over each digit... */
4775*f9fbec18Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
4776*f9fbec18Smcpowers     mp_digit  d = DIGIT(mp, ix);
4777*f9fbec18Smcpowers     int       jx;
4778*f9fbec18Smcpowers 
4779*f9fbec18Smcpowers     /* Unpack digit bytes, high order first */
4780*f9fbec18Smcpowers     for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
4781*f9fbec18Smcpowers       unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
4782*f9fbec18Smcpowers       if (!pos && !x)	/* suppress leading zeros */
4783*f9fbec18Smcpowers 	continue;
4784*f9fbec18Smcpowers       str[pos++] = x;
4785*f9fbec18Smcpowers     }
4786*f9fbec18Smcpowers   }
4787*f9fbec18Smcpowers   if (!pos)
4788*f9fbec18Smcpowers     str[pos++] = 0;
4789*f9fbec18Smcpowers   return pos;
4790*f9fbec18Smcpowers } /* end mp_to_unsigned_octets() */
4791*f9fbec18Smcpowers /* }}} */
4792*f9fbec18Smcpowers 
4793*f9fbec18Smcpowers /* {{{ mp_to_signed_octets(mp, str) */
4794*f9fbec18Smcpowers /* output a buffer of big endian octets no longer than specified. */
4795*f9fbec18Smcpowers mp_err
4796*f9fbec18Smcpowers mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
4797*f9fbec18Smcpowers {
4798*f9fbec18Smcpowers   int  ix, pos = 0;
4799*f9fbec18Smcpowers   int  bytes;
4800*f9fbec18Smcpowers 
4801*f9fbec18Smcpowers   ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
4802*f9fbec18Smcpowers 
4803*f9fbec18Smcpowers   bytes = mp_unsigned_octet_size(mp);
4804*f9fbec18Smcpowers   ARGCHK(bytes <= maxlen, MP_BADARG);
4805*f9fbec18Smcpowers 
4806*f9fbec18Smcpowers   /* Iterate over each digit... */
4807*f9fbec18Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
4808*f9fbec18Smcpowers     mp_digit  d = DIGIT(mp, ix);
4809*f9fbec18Smcpowers     int       jx;
4810*f9fbec18Smcpowers 
4811*f9fbec18Smcpowers     /* Unpack digit bytes, high order first */
4812*f9fbec18Smcpowers     for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
4813*f9fbec18Smcpowers       unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
4814*f9fbec18Smcpowers       if (!pos) {
4815*f9fbec18Smcpowers 	if (!x)		/* suppress leading zeros */
4816*f9fbec18Smcpowers 	  continue;
4817*f9fbec18Smcpowers 	if (x & 0x80) { /* add one leading zero to make output positive.  */
4818*f9fbec18Smcpowers 	  ARGCHK(bytes + 1 <= maxlen, MP_BADARG);
4819*f9fbec18Smcpowers 	  if (bytes + 1 > maxlen)
4820*f9fbec18Smcpowers 	    return MP_BADARG;
4821*f9fbec18Smcpowers 	  str[pos++] = 0;
4822*f9fbec18Smcpowers 	}
4823*f9fbec18Smcpowers       }
4824*f9fbec18Smcpowers       str[pos++] = x;
4825*f9fbec18Smcpowers     }
4826*f9fbec18Smcpowers   }
4827*f9fbec18Smcpowers   if (!pos)
4828*f9fbec18Smcpowers     str[pos++] = 0;
4829*f9fbec18Smcpowers   return pos;
4830*f9fbec18Smcpowers } /* end mp_to_signed_octets() */
4831*f9fbec18Smcpowers /* }}} */
4832*f9fbec18Smcpowers 
4833*f9fbec18Smcpowers /* {{{ mp_to_fixlen_octets(mp, str) */
4834*f9fbec18Smcpowers /* output a buffer of big endian octets exactly as long as requested. */
4835*f9fbec18Smcpowers mp_err
4836*f9fbec18Smcpowers mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length)
4837*f9fbec18Smcpowers {
4838*f9fbec18Smcpowers   int  ix, pos = 0;
4839*f9fbec18Smcpowers   int  bytes;
4840*f9fbec18Smcpowers 
4841*f9fbec18Smcpowers   ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
4842*f9fbec18Smcpowers 
4843*f9fbec18Smcpowers   bytes = mp_unsigned_octet_size(mp);
4844*f9fbec18Smcpowers   ARGCHK(bytes <= length, MP_BADARG);
4845*f9fbec18Smcpowers 
4846*f9fbec18Smcpowers   /* place any needed leading zeros */
4847*f9fbec18Smcpowers   for (;length > bytes; --length) {
4848*f9fbec18Smcpowers 	*str++ = 0;
4849*f9fbec18Smcpowers   }
4850*f9fbec18Smcpowers 
4851*f9fbec18Smcpowers   /* Iterate over each digit... */
4852*f9fbec18Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
4853*f9fbec18Smcpowers     mp_digit  d = DIGIT(mp, ix);
4854*f9fbec18Smcpowers     int       jx;
4855*f9fbec18Smcpowers 
4856*f9fbec18Smcpowers     /* Unpack digit bytes, high order first */
4857*f9fbec18Smcpowers     for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
4858*f9fbec18Smcpowers       unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
4859*f9fbec18Smcpowers       if (!pos && !x)	/* suppress leading zeros */
4860*f9fbec18Smcpowers 	continue;
4861*f9fbec18Smcpowers       str[pos++] = x;
4862*f9fbec18Smcpowers     }
4863*f9fbec18Smcpowers   }
4864*f9fbec18Smcpowers   if (!pos)
4865*f9fbec18Smcpowers     str[pos++] = 0;
4866*f9fbec18Smcpowers   return MP_OKAY;
4867*f9fbec18Smcpowers } /* end mp_to_fixlen_octets() */
4868*f9fbec18Smcpowers /* }}} */
4869*f9fbec18Smcpowers 
4870*f9fbec18Smcpowers 
4871*f9fbec18Smcpowers /*------------------------------------------------------------------------*/
4872*f9fbec18Smcpowers /* HERE THERE BE DRAGONS                                                  */
4873