xref: /onnv-gate/usr/src/common/mpi/mpi.c (revision 13066:6cb0e0fdae86)
1*13066SDina.Nimeh@Sun.COM /* BEGIN CSTYLED */
25697Smcpowers /*
35697Smcpowers  *  mpi.c
45697Smcpowers  *
55697Smcpowers  *  Arbitrary precision integer arithmetic library
65697Smcpowers  *
75697Smcpowers  * ***** BEGIN LICENSE BLOCK *****
85697Smcpowers  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
95697Smcpowers  *
105697Smcpowers  * The contents of this file are subject to the Mozilla Public License Version
115697Smcpowers  * 1.1 (the "License"); you may not use this file except in compliance with
125697Smcpowers  * the License. You may obtain a copy of the License at
135697Smcpowers  * http://www.mozilla.org/MPL/
145697Smcpowers  *
155697Smcpowers  * Software distributed under the License is distributed on an "AS IS" basis,
165697Smcpowers  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
175697Smcpowers  * for the specific language governing rights and limitations under the
185697Smcpowers  * License.
195697Smcpowers  *
205697Smcpowers  * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
215697Smcpowers  *
225697Smcpowers  * The Initial Developer of the Original Code is
235697Smcpowers  * Michael J. Fromberger.
245697Smcpowers  * Portions created by the Initial Developer are Copyright (C) 1998
255697Smcpowers  * the Initial Developer. All Rights Reserved.
265697Smcpowers  *
275697Smcpowers  * Contributor(s):
285697Smcpowers  *   Netscape Communications Corporation
295697Smcpowers  *   Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
305697Smcpowers  *
315697Smcpowers  * Alternatively, the contents of this file may be used under the terms of
325697Smcpowers  * either the GNU General Public License Version 2 or later (the "GPL"), or
335697Smcpowers  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
345697Smcpowers  * in which case the provisions of the GPL or the LGPL are applicable instead
355697Smcpowers  * of those above. If you wish to allow use of your version of this file only
365697Smcpowers  * under the terms of either the GPL or the LGPL, and not to allow others to
375697Smcpowers  * use your version of this file under the terms of the MPL, indicate your
385697Smcpowers  * decision by deleting the provisions above and replace them with the notice
395697Smcpowers  * and other provisions required by the GPL or the LGPL. If you do not delete
405697Smcpowers  * the provisions above, a recipient may use your version of this file under
415697Smcpowers  * the terms of any one of the MPL, the GPL or the LGPL.
425697Smcpowers  *
435697Smcpowers  * ***** END LICENSE BLOCK ***** */
445697Smcpowers /*
45*13066SDina.Nimeh@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
465697Smcpowers  *
475697Smcpowers  * Sun elects to use this software under the MPL license.
485697Smcpowers  */
495697Smcpowers 
505697Smcpowers /* $Id: mpi.c,v 1.45 2006/09/29 20:12:21 alexei.volkov.bugs%sun.com Exp $ */
515697Smcpowers 
525697Smcpowers #include "mpi-priv.h"
535697Smcpowers #if defined(OSF1)
545697Smcpowers #include <c_asm.h>
555697Smcpowers #endif
565697Smcpowers 
575697Smcpowers #if MP_LOGTAB
585697Smcpowers /*
595697Smcpowers   A table of the logs of 2 for various bases (the 0 and 1 entries of
605697Smcpowers   this table are meaningless and should not be referenced).
615697Smcpowers 
625697Smcpowers   This table is used to compute output lengths for the mp_toradix()
635697Smcpowers   function.  Since a number n in radix r takes up about log_r(n)
645697Smcpowers   digits, we estimate the output size by taking the least integer
655697Smcpowers   greater than log_r(n), where:
665697Smcpowers 
675697Smcpowers   log_r(n) = log_2(n) * log_r(2)
685697Smcpowers 
695697Smcpowers   This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
705697Smcpowers   which are the output bases supported.
715697Smcpowers  */
725697Smcpowers #include "logtab.h"
735697Smcpowers #endif
745697Smcpowers 
755697Smcpowers /* {{{ Constant strings */
765697Smcpowers 
775697Smcpowers /* Constant strings returned by mp_strerror() */
785697Smcpowers static const char *mp_err_string[] = {
795697Smcpowers   "unknown result code",     /* say what?            */
805697Smcpowers   "boolean true",            /* MP_OKAY, MP_YES      */
815697Smcpowers   "boolean false",           /* MP_NO                */
825697Smcpowers   "out of memory",           /* MP_MEM               */
835697Smcpowers   "argument out of range",   /* MP_RANGE             */
845697Smcpowers   "invalid input parameter", /* MP_BADARG            */
855697Smcpowers   "result is undefined"      /* MP_UNDEF             */
865697Smcpowers };
875697Smcpowers 
885697Smcpowers /* Value to digit maps for radix conversion   */
895697Smcpowers 
905697Smcpowers /* s_dmap_1 - standard digits and letters */
915697Smcpowers static const char *s_dmap_1 =
925697Smcpowers   "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
935697Smcpowers 
945697Smcpowers /* }}} */
955697Smcpowers 
965697Smcpowers unsigned long mp_allocs;
975697Smcpowers unsigned long mp_frees;
985697Smcpowers unsigned long mp_copies;
995697Smcpowers 
1005697Smcpowers /* {{{ Default precision manipulation */
1015697Smcpowers 
1025697Smcpowers /* Default precision for newly created mp_int's      */
1035697Smcpowers static mp_size s_mp_defprec = MP_DEFPREC;
1045697Smcpowers 
mp_get_prec(void)1055697Smcpowers mp_size mp_get_prec(void)
1065697Smcpowers {
1075697Smcpowers   return s_mp_defprec;
1085697Smcpowers 
1095697Smcpowers } /* end mp_get_prec() */
1105697Smcpowers 
mp_set_prec(mp_size prec)1115697Smcpowers void         mp_set_prec(mp_size prec)
1125697Smcpowers {
1135697Smcpowers   if(prec == 0)
1145697Smcpowers     s_mp_defprec = MP_DEFPREC;
1155697Smcpowers   else
1165697Smcpowers     s_mp_defprec = prec;
1175697Smcpowers 
1185697Smcpowers } /* end mp_set_prec() */
1195697Smcpowers 
1205697Smcpowers /* }}} */
1215697Smcpowers 
1225697Smcpowers /*------------------------------------------------------------------------*/
1235697Smcpowers /* {{{ mp_init(mp, kmflag) */
1245697Smcpowers 
1255697Smcpowers /*
1265697Smcpowers   mp_init(mp, kmflag)
1275697Smcpowers 
1285697Smcpowers   Initialize a new zero-valued mp_int.  Returns MP_OKAY if successful,
1295697Smcpowers   MP_MEM if memory could not be allocated for the structure.
1305697Smcpowers  */
1315697Smcpowers 
mp_init(mp_int * mp,int kmflag)1325697Smcpowers mp_err mp_init(mp_int *mp, int kmflag)
1335697Smcpowers {
1345697Smcpowers   return mp_init_size(mp, s_mp_defprec, kmflag);
1355697Smcpowers 
1365697Smcpowers } /* end mp_init() */
1375697Smcpowers 
1385697Smcpowers /* }}} */
1395697Smcpowers 
1405697Smcpowers /* {{{ mp_init_size(mp, prec, kmflag) */
1415697Smcpowers 
1425697Smcpowers /*
1435697Smcpowers   mp_init_size(mp, prec, kmflag)
1445697Smcpowers 
1455697Smcpowers   Initialize a new zero-valued mp_int with at least the given
1465697Smcpowers   precision; returns MP_OKAY if successful, or MP_MEM if memory could
1475697Smcpowers   not be allocated for the structure.
1485697Smcpowers  */
1495697Smcpowers 
mp_init_size(mp_int * mp,mp_size prec,int kmflag)1505697Smcpowers mp_err mp_init_size(mp_int *mp, mp_size prec, int kmflag)
1515697Smcpowers {
1525697Smcpowers   ARGCHK(mp != NULL && prec > 0, MP_BADARG);
1535697Smcpowers 
1545697Smcpowers   prec = MP_ROUNDUP(prec, s_mp_defprec);
1555697Smcpowers   if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit), kmflag)) == NULL)
1565697Smcpowers     return MP_MEM;
1575697Smcpowers 
1585697Smcpowers   SIGN(mp) = ZPOS;
1595697Smcpowers   USED(mp) = 1;
1605697Smcpowers   ALLOC(mp) = prec;
161*13066SDina.Nimeh@Sun.COM   FLAG(mp) = kmflag;
1625697Smcpowers 
1635697Smcpowers   return MP_OKAY;
1645697Smcpowers 
1655697Smcpowers } /* end mp_init_size() */
1665697Smcpowers 
1675697Smcpowers /* }}} */
1685697Smcpowers 
1695697Smcpowers /* {{{ mp_init_copy(mp, from) */
1705697Smcpowers 
1715697Smcpowers /*
1725697Smcpowers   mp_init_copy(mp, from)
1735697Smcpowers 
1745697Smcpowers   Initialize mp as an exact copy of from.  Returns MP_OKAY if
1755697Smcpowers   successful, MP_MEM if memory could not be allocated for the new
1765697Smcpowers   structure.
1775697Smcpowers  */
1785697Smcpowers 
mp_init_copy(mp_int * mp,const mp_int * from)1795697Smcpowers mp_err mp_init_copy(mp_int *mp, const mp_int *from)
1805697Smcpowers {
1815697Smcpowers   ARGCHK(mp != NULL && from != NULL, MP_BADARG);
1825697Smcpowers 
1835697Smcpowers   if(mp == from)
1845697Smcpowers     return MP_OKAY;
1855697Smcpowers 
1865697Smcpowers   if((DIGITS(mp) = s_mp_alloc(ALLOC(from), sizeof(mp_digit), FLAG(from))) == NULL)
1875697Smcpowers     return MP_MEM;
1885697Smcpowers 
1895697Smcpowers   s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));
1905697Smcpowers   USED(mp) = USED(from);
1915697Smcpowers   ALLOC(mp) = ALLOC(from);
1925697Smcpowers   SIGN(mp) = SIGN(from);
1935697Smcpowers   FLAG(mp) = FLAG(from);
1945697Smcpowers 
1955697Smcpowers   return MP_OKAY;
1965697Smcpowers 
1975697Smcpowers } /* end mp_init_copy() */
1985697Smcpowers 
1995697Smcpowers /* }}} */
2005697Smcpowers 
2015697Smcpowers /* {{{ mp_copy(from, to) */
2025697Smcpowers 
2035697Smcpowers /*
2045697Smcpowers   mp_copy(from, to)
2055697Smcpowers 
2065697Smcpowers   Copies the mp_int 'from' to the mp_int 'to'.  It is presumed that
2075697Smcpowers   'to' has already been initialized (if not, use mp_init_copy()
2085697Smcpowers   instead). If 'from' and 'to' are identical, nothing happens.
2095697Smcpowers  */
2105697Smcpowers 
mp_copy(const mp_int * from,mp_int * to)2115697Smcpowers mp_err mp_copy(const mp_int *from, mp_int *to)
2125697Smcpowers {
2135697Smcpowers   ARGCHK(from != NULL && to != NULL, MP_BADARG);
2145697Smcpowers 
2155697Smcpowers   if(from == to)
2165697Smcpowers     return MP_OKAY;
2175697Smcpowers 
2185697Smcpowers   ++mp_copies;
2195697Smcpowers   { /* copy */
2205697Smcpowers     mp_digit   *tmp;
2215697Smcpowers 
2225697Smcpowers     /*
2235697Smcpowers       If the allocated buffer in 'to' already has enough space to hold
2245697Smcpowers       all the used digits of 'from', we'll re-use it to avoid hitting
2255697Smcpowers       the memory allocater more than necessary; otherwise, we'd have
2265697Smcpowers       to grow anyway, so we just allocate a hunk and make the copy as
2275697Smcpowers       usual
2285697Smcpowers      */
2295697Smcpowers     if(ALLOC(to) >= USED(from)) {
2305697Smcpowers       s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));
2315697Smcpowers       s_mp_copy(DIGITS(from), DIGITS(to), USED(from));
2325697Smcpowers 
2335697Smcpowers     } else {
2345697Smcpowers       if((tmp = s_mp_alloc(ALLOC(from), sizeof(mp_digit), FLAG(from))) == NULL)
2355697Smcpowers 	return MP_MEM;
2365697Smcpowers 
2375697Smcpowers       s_mp_copy(DIGITS(from), tmp, USED(from));
2385697Smcpowers 
2395697Smcpowers       if(DIGITS(to) != NULL) {
2405697Smcpowers #if MP_CRYPTO
2415697Smcpowers 	s_mp_setz(DIGITS(to), ALLOC(to));
2425697Smcpowers #endif
2435697Smcpowers 	s_mp_free(DIGITS(to), ALLOC(to));
2445697Smcpowers       }
2455697Smcpowers 
2465697Smcpowers       DIGITS(to) = tmp;
2475697Smcpowers       ALLOC(to) = ALLOC(from);
2485697Smcpowers     }
2495697Smcpowers 
2505697Smcpowers     /* Copy the precision and sign from the original */
2515697Smcpowers     USED(to) = USED(from);
2525697Smcpowers     SIGN(to) = SIGN(from);
253*13066SDina.Nimeh@Sun.COM     FLAG(to) = FLAG(from);
2545697Smcpowers   } /* end copy */
2555697Smcpowers 
2565697Smcpowers   return MP_OKAY;
2575697Smcpowers 
2585697Smcpowers } /* end mp_copy() */
2595697Smcpowers 
2605697Smcpowers /* }}} */
2615697Smcpowers 
2625697Smcpowers /* {{{ mp_exch(mp1, mp2) */
2635697Smcpowers 
2645697Smcpowers /*
2655697Smcpowers   mp_exch(mp1, mp2)
2665697Smcpowers 
2675697Smcpowers   Exchange mp1 and mp2 without allocating any intermediate memory
2685697Smcpowers   (well, unless you count the stack space needed for this call and the
2695697Smcpowers   locals it creates...).  This cannot fail.
2705697Smcpowers  */
2715697Smcpowers 
mp_exch(mp_int * mp1,mp_int * mp2)2725697Smcpowers void mp_exch(mp_int *mp1, mp_int *mp2)
2735697Smcpowers {
2745697Smcpowers #if MP_ARGCHK == 2
2755697Smcpowers   assert(mp1 != NULL && mp2 != NULL);
2765697Smcpowers #else
2775697Smcpowers   if(mp1 == NULL || mp2 == NULL)
2785697Smcpowers     return;
2795697Smcpowers #endif
2805697Smcpowers 
2815697Smcpowers   s_mp_exch(mp1, mp2);
2825697Smcpowers 
2835697Smcpowers } /* end mp_exch() */
2845697Smcpowers 
2855697Smcpowers /* }}} */
2865697Smcpowers 
2875697Smcpowers /* {{{ mp_clear(mp) */
2885697Smcpowers 
2895697Smcpowers /*
2905697Smcpowers   mp_clear(mp)
2915697Smcpowers 
2925697Smcpowers   Release the storage used by an mp_int, and void its fields so that
2935697Smcpowers   if someone calls mp_clear() again for the same int later, we won't
2945697Smcpowers   get tollchocked.
2955697Smcpowers  */
2965697Smcpowers 
mp_clear(mp_int * mp)2975697Smcpowers void   mp_clear(mp_int *mp)
2985697Smcpowers {
2995697Smcpowers   if(mp == NULL)
3005697Smcpowers     return;
3015697Smcpowers 
3025697Smcpowers   if(DIGITS(mp) != NULL) {
3035697Smcpowers #if MP_CRYPTO
3045697Smcpowers     s_mp_setz(DIGITS(mp), ALLOC(mp));
3055697Smcpowers #endif
3065697Smcpowers     s_mp_free(DIGITS(mp), ALLOC(mp));
3075697Smcpowers     DIGITS(mp) = NULL;
3085697Smcpowers   }
3095697Smcpowers 
3105697Smcpowers   USED(mp) = 0;
3115697Smcpowers   ALLOC(mp) = 0;
3125697Smcpowers 
3135697Smcpowers } /* end mp_clear() */
3145697Smcpowers 
3155697Smcpowers /* }}} */
3165697Smcpowers 
3175697Smcpowers /* {{{ mp_zero(mp) */
3185697Smcpowers 
3195697Smcpowers /*
3205697Smcpowers   mp_zero(mp)
3215697Smcpowers 
3225697Smcpowers   Set mp to zero.  Does not change the allocated size of the structure,
3235697Smcpowers   and therefore cannot fail (except on a bad argument, which we ignore)
3245697Smcpowers  */
mp_zero(mp_int * mp)3255697Smcpowers void   mp_zero(mp_int *mp)
3265697Smcpowers {
3275697Smcpowers   if(mp == NULL)
3285697Smcpowers     return;
3295697Smcpowers 
3305697Smcpowers   s_mp_setz(DIGITS(mp), ALLOC(mp));
3315697Smcpowers   USED(mp) = 1;
3325697Smcpowers   SIGN(mp) = ZPOS;
3335697Smcpowers 
3345697Smcpowers } /* end mp_zero() */
3355697Smcpowers 
3365697Smcpowers /* }}} */
3375697Smcpowers 
3385697Smcpowers /* {{{ mp_set(mp, d) */
3395697Smcpowers 
mp_set(mp_int * mp,mp_digit d)3405697Smcpowers void   mp_set(mp_int *mp, mp_digit d)
3415697Smcpowers {
3425697Smcpowers   if(mp == NULL)
3435697Smcpowers     return;
3445697Smcpowers 
3455697Smcpowers   mp_zero(mp);
3465697Smcpowers   DIGIT(mp, 0) = d;
3475697Smcpowers 
3485697Smcpowers } /* end mp_set() */
3495697Smcpowers 
3505697Smcpowers /* }}} */
3515697Smcpowers 
3525697Smcpowers /* {{{ mp_set_int(mp, z) */
3535697Smcpowers 
mp_set_int(mp_int * mp,long z)3545697Smcpowers mp_err mp_set_int(mp_int *mp, long z)
3555697Smcpowers {
3565697Smcpowers   int            ix;
3575697Smcpowers   unsigned long  v = labs(z);
3585697Smcpowers   mp_err         res;
3595697Smcpowers 
3605697Smcpowers   ARGCHK(mp != NULL, MP_BADARG);
3615697Smcpowers 
3625697Smcpowers   mp_zero(mp);
3635697Smcpowers   if(z == 0)
3645697Smcpowers     return MP_OKAY;  /* shortcut for zero */
3655697Smcpowers 
3665697Smcpowers   if (sizeof v <= sizeof(mp_digit)) {
3675697Smcpowers     DIGIT(mp,0) = v;
3685697Smcpowers   } else {
3695697Smcpowers     for (ix = sizeof(long) - 1; ix >= 0; ix--) {
3705697Smcpowers       if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
3715697Smcpowers 	return res;
3725697Smcpowers 
3735697Smcpowers       res = s_mp_add_d(mp, (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
3745697Smcpowers       if (res != MP_OKAY)
3755697Smcpowers 	return res;
3765697Smcpowers     }
3775697Smcpowers   }
3785697Smcpowers   if(z < 0)
3795697Smcpowers     SIGN(mp) = NEG;
3805697Smcpowers 
3815697Smcpowers   return MP_OKAY;
3825697Smcpowers 
3835697Smcpowers } /* end mp_set_int() */
3845697Smcpowers 
3855697Smcpowers /* }}} */
3865697Smcpowers 
3875697Smcpowers /* {{{ mp_set_ulong(mp, z) */
3885697Smcpowers 
mp_set_ulong(mp_int * mp,unsigned long z)3895697Smcpowers mp_err mp_set_ulong(mp_int *mp, unsigned long z)
3905697Smcpowers {
3915697Smcpowers   int            ix;
3925697Smcpowers   mp_err         res;
3935697Smcpowers 
3945697Smcpowers   ARGCHK(mp != NULL, MP_BADARG);
3955697Smcpowers 
3965697Smcpowers   mp_zero(mp);
3975697Smcpowers   if(z == 0)
3985697Smcpowers     return MP_OKAY;  /* shortcut for zero */
3995697Smcpowers 
4005697Smcpowers   if (sizeof z <= sizeof(mp_digit)) {
4015697Smcpowers     DIGIT(mp,0) = z;
4025697Smcpowers   } else {
4035697Smcpowers     for (ix = sizeof(long) - 1; ix >= 0; ix--) {
4045697Smcpowers       if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
4055697Smcpowers 	return res;
4065697Smcpowers 
4075697Smcpowers       res = s_mp_add_d(mp, (mp_digit)((z >> (ix * CHAR_BIT)) & UCHAR_MAX));
4085697Smcpowers       if (res != MP_OKAY)
4095697Smcpowers 	return res;
4105697Smcpowers     }
4115697Smcpowers   }
4125697Smcpowers   return MP_OKAY;
4135697Smcpowers } /* end mp_set_ulong() */
4145697Smcpowers 
4155697Smcpowers /* }}} */
4165697Smcpowers 
4175697Smcpowers /*------------------------------------------------------------------------*/
4185697Smcpowers /* {{{ Digit arithmetic */
4195697Smcpowers 
4205697Smcpowers /* {{{ mp_add_d(a, d, b) */
4215697Smcpowers 
4225697Smcpowers /*
4235697Smcpowers   mp_add_d(a, d, b)
4245697Smcpowers 
4255697Smcpowers   Compute the sum b = a + d, for a single digit d.  Respects the sign of
4265697Smcpowers   its primary addend (single digits are unsigned anyway).
4275697Smcpowers  */
4285697Smcpowers 
mp_add_d(const mp_int * a,mp_digit d,mp_int * b)4295697Smcpowers mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b)
4305697Smcpowers {
4315697Smcpowers   mp_int   tmp;
4325697Smcpowers   mp_err   res;
4335697Smcpowers 
4345697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
4355697Smcpowers 
4365697Smcpowers   if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
4375697Smcpowers     return res;
4385697Smcpowers 
4395697Smcpowers   if(SIGN(&tmp) == ZPOS) {
4405697Smcpowers     if((res = s_mp_add_d(&tmp, d)) != MP_OKAY)
4415697Smcpowers       goto CLEANUP;
4425697Smcpowers   } else if(s_mp_cmp_d(&tmp, d) >= 0) {
4435697Smcpowers     if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY)
4445697Smcpowers       goto CLEANUP;
4455697Smcpowers   } else {
4465697Smcpowers     mp_neg(&tmp, &tmp);
4475697Smcpowers 
4485697Smcpowers     DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0);
4495697Smcpowers   }
4505697Smcpowers 
4515697Smcpowers   if(s_mp_cmp_d(&tmp, 0) == 0)
4525697Smcpowers     SIGN(&tmp) = ZPOS;
4535697Smcpowers 
4545697Smcpowers   s_mp_exch(&tmp, b);
4555697Smcpowers 
4565697Smcpowers CLEANUP:
4575697Smcpowers   mp_clear(&tmp);
4585697Smcpowers   return res;
4595697Smcpowers 
4605697Smcpowers } /* end mp_add_d() */
4615697Smcpowers 
4625697Smcpowers /* }}} */
4635697Smcpowers 
4645697Smcpowers /* {{{ mp_sub_d(a, d, b) */
4655697Smcpowers 
4665697Smcpowers /*
4675697Smcpowers   mp_sub_d(a, d, b)
4685697Smcpowers 
4695697Smcpowers   Compute the difference b = a - d, for a single digit d.  Respects the
4705697Smcpowers   sign of its subtrahend (single digits are unsigned anyway).
4715697Smcpowers  */
4725697Smcpowers 
mp_sub_d(const mp_int * a,mp_digit d,mp_int * b)4735697Smcpowers mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b)
4745697Smcpowers {
4755697Smcpowers   mp_int   tmp;
4765697Smcpowers   mp_err   res;
4775697Smcpowers 
4785697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
4795697Smcpowers 
4805697Smcpowers   if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
4815697Smcpowers     return res;
4825697Smcpowers 
4835697Smcpowers   if(SIGN(&tmp) == NEG) {
4845697Smcpowers     if((res = s_mp_add_d(&tmp, d)) != MP_OKAY)
4855697Smcpowers       goto CLEANUP;
4865697Smcpowers   } else if(s_mp_cmp_d(&tmp, d) >= 0) {
4875697Smcpowers     if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY)
4885697Smcpowers       goto CLEANUP;
4895697Smcpowers   } else {
4905697Smcpowers     mp_neg(&tmp, &tmp);
4915697Smcpowers 
4925697Smcpowers     DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0);
4935697Smcpowers     SIGN(&tmp) = NEG;
4945697Smcpowers   }
4955697Smcpowers 
4965697Smcpowers   if(s_mp_cmp_d(&tmp, 0) == 0)
4975697Smcpowers     SIGN(&tmp) = ZPOS;
4985697Smcpowers 
4995697Smcpowers   s_mp_exch(&tmp, b);
5005697Smcpowers 
5015697Smcpowers CLEANUP:
5025697Smcpowers   mp_clear(&tmp);
5035697Smcpowers   return res;
5045697Smcpowers 
5055697Smcpowers } /* end mp_sub_d() */
5065697Smcpowers 
5075697Smcpowers /* }}} */
5085697Smcpowers 
5095697Smcpowers /* {{{ mp_mul_d(a, d, b) */
5105697Smcpowers 
5115697Smcpowers /*
5125697Smcpowers   mp_mul_d(a, d, b)
5135697Smcpowers 
5145697Smcpowers   Compute the product b = a * d, for a single digit d.  Respects the sign
5155697Smcpowers   of its multiplicand (single digits are unsigned anyway)
5165697Smcpowers  */
5175697Smcpowers 
mp_mul_d(const mp_int * a,mp_digit d,mp_int * b)5185697Smcpowers mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b)
5195697Smcpowers {
5205697Smcpowers   mp_err  res;
5215697Smcpowers 
5225697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
5235697Smcpowers 
5245697Smcpowers   if(d == 0) {
5255697Smcpowers     mp_zero(b);
5265697Smcpowers     return MP_OKAY;
5275697Smcpowers   }
5285697Smcpowers 
5295697Smcpowers   if((res = mp_copy(a, b)) != MP_OKAY)
5305697Smcpowers     return res;
5315697Smcpowers 
5325697Smcpowers   res = s_mp_mul_d(b, d);
5335697Smcpowers 
5345697Smcpowers   return res;
5355697Smcpowers 
5365697Smcpowers } /* end mp_mul_d() */
5375697Smcpowers 
5385697Smcpowers /* }}} */
5395697Smcpowers 
5405697Smcpowers /* {{{ mp_mul_2(a, c) */
5415697Smcpowers 
mp_mul_2(const mp_int * a,mp_int * c)5425697Smcpowers mp_err mp_mul_2(const mp_int *a, mp_int *c)
5435697Smcpowers {
5445697Smcpowers   mp_err  res;
5455697Smcpowers 
5465697Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
5475697Smcpowers 
5485697Smcpowers   if((res = mp_copy(a, c)) != MP_OKAY)
5495697Smcpowers     return res;
5505697Smcpowers 
5515697Smcpowers   return s_mp_mul_2(c);
5525697Smcpowers 
5535697Smcpowers } /* end mp_mul_2() */
5545697Smcpowers 
5555697Smcpowers /* }}} */
5565697Smcpowers 
5575697Smcpowers /* {{{ mp_div_d(a, d, q, r) */
5585697Smcpowers 
5595697Smcpowers /*
5605697Smcpowers   mp_div_d(a, d, q, r)
5615697Smcpowers 
5625697Smcpowers   Compute the quotient q = a / d and remainder r = a mod d, for a
5635697Smcpowers   single digit d.  Respects the sign of its divisor (single digits are
5645697Smcpowers   unsigned anyway).
5655697Smcpowers  */
5665697Smcpowers 
mp_div_d(const mp_int * a,mp_digit d,mp_int * q,mp_digit * r)5675697Smcpowers mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
5685697Smcpowers {
5695697Smcpowers   mp_err   res;
5705697Smcpowers   mp_int   qp;
5715697Smcpowers   mp_digit rem;
5725697Smcpowers   int      pow;
5735697Smcpowers 
5745697Smcpowers   ARGCHK(a != NULL, MP_BADARG);
5755697Smcpowers 
5765697Smcpowers   if(d == 0)
5775697Smcpowers     return MP_RANGE;
5785697Smcpowers 
5795697Smcpowers   /* Shortcut for powers of two ... */
5805697Smcpowers   if((pow = s_mp_ispow2d(d)) >= 0) {
5815697Smcpowers     mp_digit  mask;
5825697Smcpowers 
5835697Smcpowers     mask = ((mp_digit)1 << pow) - 1;
5845697Smcpowers     rem = DIGIT(a, 0) & mask;
5855697Smcpowers 
5865697Smcpowers     if(q) {
5875697Smcpowers       mp_copy(a, q);
5885697Smcpowers       s_mp_div_2d(q, pow);
5895697Smcpowers     }
5905697Smcpowers 
5915697Smcpowers     if(r)
5925697Smcpowers       *r = rem;
5935697Smcpowers 
5945697Smcpowers     return MP_OKAY;
5955697Smcpowers   }
5965697Smcpowers 
5975697Smcpowers   if((res = mp_init_copy(&qp, a)) != MP_OKAY)
5985697Smcpowers     return res;
5995697Smcpowers 
6005697Smcpowers   res = s_mp_div_d(&qp, d, &rem);
6015697Smcpowers 
6025697Smcpowers   if(s_mp_cmp_d(&qp, 0) == 0)
6035697Smcpowers     SIGN(q) = ZPOS;
6045697Smcpowers 
6055697Smcpowers   if(r)
6065697Smcpowers     *r = rem;
6075697Smcpowers 
6085697Smcpowers   if(q)
6095697Smcpowers     s_mp_exch(&qp, q);
6105697Smcpowers 
6115697Smcpowers   mp_clear(&qp);
6125697Smcpowers   return res;
6135697Smcpowers 
6145697Smcpowers } /* end mp_div_d() */
6155697Smcpowers 
6165697Smcpowers /* }}} */
6175697Smcpowers 
6185697Smcpowers /* {{{ mp_div_2(a, c) */
6195697Smcpowers 
6205697Smcpowers /*
6215697Smcpowers   mp_div_2(a, c)
6225697Smcpowers 
6235697Smcpowers   Compute c = a / 2, disregarding the remainder.
6245697Smcpowers  */
6255697Smcpowers 
mp_div_2(const mp_int * a,mp_int * c)6265697Smcpowers mp_err mp_div_2(const mp_int *a, mp_int *c)
6275697Smcpowers {
6285697Smcpowers   mp_err  res;
6295697Smcpowers 
6305697Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
6315697Smcpowers 
6325697Smcpowers   if((res = mp_copy(a, c)) != MP_OKAY)
6335697Smcpowers     return res;
6345697Smcpowers 
6355697Smcpowers   s_mp_div_2(c);
6365697Smcpowers 
6375697Smcpowers   return MP_OKAY;
6385697Smcpowers 
6395697Smcpowers } /* end mp_div_2() */
6405697Smcpowers 
6415697Smcpowers /* }}} */
6425697Smcpowers 
6435697Smcpowers /* {{{ mp_expt_d(a, d, b) */
6445697Smcpowers 
mp_expt_d(const mp_int * a,mp_digit d,mp_int * c)6455697Smcpowers mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c)
6465697Smcpowers {
6475697Smcpowers   mp_int   s, x;
6485697Smcpowers   mp_err   res;
6495697Smcpowers 
6505697Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
6515697Smcpowers 
6525697Smcpowers   if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
6535697Smcpowers     return res;
6545697Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY)
6555697Smcpowers     goto X;
6565697Smcpowers 
6575697Smcpowers   DIGIT(&s, 0) = 1;
6585697Smcpowers 
6595697Smcpowers   while(d != 0) {
6605697Smcpowers     if(d & 1) {
6615697Smcpowers       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
6625697Smcpowers 	goto CLEANUP;
6635697Smcpowers     }
6645697Smcpowers 
6655697Smcpowers     d /= 2;
6665697Smcpowers 
6675697Smcpowers     if((res = s_mp_sqr(&x)) != MP_OKAY)
6685697Smcpowers       goto CLEANUP;
6695697Smcpowers   }
6705697Smcpowers 
6715697Smcpowers   s_mp_exch(&s, c);
6725697Smcpowers 
6735697Smcpowers CLEANUP:
6745697Smcpowers   mp_clear(&x);
6755697Smcpowers X:
6765697Smcpowers   mp_clear(&s);
6775697Smcpowers 
6785697Smcpowers   return res;
6795697Smcpowers 
6805697Smcpowers } /* end mp_expt_d() */
6815697Smcpowers 
6825697Smcpowers /* }}} */
6835697Smcpowers 
6845697Smcpowers /* }}} */
6855697Smcpowers 
6865697Smcpowers /*------------------------------------------------------------------------*/
6875697Smcpowers /* {{{ Full arithmetic */
6885697Smcpowers 
6895697Smcpowers /* {{{ mp_abs(a, b) */
6905697Smcpowers 
6915697Smcpowers /*
6925697Smcpowers   mp_abs(a, b)
6935697Smcpowers 
6945697Smcpowers   Compute b = |a|.  'a' and 'b' may be identical.
6955697Smcpowers  */
6965697Smcpowers 
mp_abs(const mp_int * a,mp_int * b)6975697Smcpowers mp_err mp_abs(const mp_int *a, mp_int *b)
6985697Smcpowers {
6995697Smcpowers   mp_err   res;
7005697Smcpowers 
7015697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
7025697Smcpowers 
7035697Smcpowers   if((res = mp_copy(a, b)) != MP_OKAY)
7045697Smcpowers     return res;
7055697Smcpowers 
7065697Smcpowers   SIGN(b) = ZPOS;
7075697Smcpowers 
7085697Smcpowers   return MP_OKAY;
7095697Smcpowers 
7105697Smcpowers } /* end mp_abs() */
7115697Smcpowers 
7125697Smcpowers /* }}} */
7135697Smcpowers 
7145697Smcpowers /* {{{ mp_neg(a, b) */
7155697Smcpowers 
7165697Smcpowers /*
7175697Smcpowers   mp_neg(a, b)
7185697Smcpowers 
7195697Smcpowers   Compute b = -a.  'a' and 'b' may be identical.
7205697Smcpowers  */
7215697Smcpowers 
mp_neg(const mp_int * a,mp_int * b)7225697Smcpowers mp_err mp_neg(const mp_int *a, mp_int *b)
7235697Smcpowers {
7245697Smcpowers   mp_err   res;
7255697Smcpowers 
7265697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
7275697Smcpowers 
7285697Smcpowers   if((res = mp_copy(a, b)) != MP_OKAY)
7295697Smcpowers     return res;
7305697Smcpowers 
7315697Smcpowers   if(s_mp_cmp_d(b, 0) == MP_EQ)
7325697Smcpowers     SIGN(b) = ZPOS;
7335697Smcpowers   else
7345697Smcpowers     SIGN(b) = (SIGN(b) == NEG) ? ZPOS : NEG;
7355697Smcpowers 
7365697Smcpowers   return MP_OKAY;
7375697Smcpowers 
7385697Smcpowers } /* end mp_neg() */
7395697Smcpowers 
7405697Smcpowers /* }}} */
7415697Smcpowers 
7425697Smcpowers /* {{{ mp_add(a, b, c) */
7435697Smcpowers 
7445697Smcpowers /*
7455697Smcpowers   mp_add(a, b, c)
7465697Smcpowers 
7475697Smcpowers   Compute c = a + b.  All parameters may be identical.
7485697Smcpowers  */
7495697Smcpowers 
mp_add(const mp_int * a,const mp_int * b,mp_int * c)7505697Smcpowers mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c)
7515697Smcpowers {
7525697Smcpowers   mp_err  res;
7535697Smcpowers 
7545697Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
7555697Smcpowers 
7565697Smcpowers   if(SIGN(a) == SIGN(b)) { /* same sign:  add values, keep sign */
7575697Smcpowers     MP_CHECKOK( s_mp_add_3arg(a, b, c) );
7585697Smcpowers   } else if(s_mp_cmp(a, b) >= 0) {  /* different sign: |a| >= |b|   */
7595697Smcpowers     MP_CHECKOK( s_mp_sub_3arg(a, b, c) );
7605697Smcpowers   } else {                          /* different sign: |a|  < |b|   */
7615697Smcpowers     MP_CHECKOK( s_mp_sub_3arg(b, a, c) );
7625697Smcpowers   }
7635697Smcpowers 
7645697Smcpowers   if (s_mp_cmp_d(c, 0) == MP_EQ)
7655697Smcpowers     SIGN(c) = ZPOS;
7665697Smcpowers 
7675697Smcpowers CLEANUP:
7685697Smcpowers   return res;
7695697Smcpowers 
7705697Smcpowers } /* end mp_add() */
7715697Smcpowers 
7725697Smcpowers /* }}} */
7735697Smcpowers 
7745697Smcpowers /* {{{ mp_sub(a, b, c) */
7755697Smcpowers 
7765697Smcpowers /*
7775697Smcpowers   mp_sub(a, b, c)
7785697Smcpowers 
7795697Smcpowers   Compute c = a - b.  All parameters may be identical.
7805697Smcpowers  */
7815697Smcpowers 
mp_sub(const mp_int * a,const mp_int * b,mp_int * c)7825697Smcpowers mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
7835697Smcpowers {
7845697Smcpowers   mp_err  res;
7855697Smcpowers   int     magDiff;
7865697Smcpowers 
7875697Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
7885697Smcpowers 
7895697Smcpowers   if (a == b) {
7905697Smcpowers     mp_zero(c);
7915697Smcpowers     return MP_OKAY;
7925697Smcpowers   }
7935697Smcpowers 
7945697Smcpowers   if (MP_SIGN(a) != MP_SIGN(b)) {
7955697Smcpowers     MP_CHECKOK( s_mp_add_3arg(a, b, c) );
7965697Smcpowers   } else if (!(magDiff = s_mp_cmp(a, b))) {
7975697Smcpowers     mp_zero(c);
7985697Smcpowers     res = MP_OKAY;
7995697Smcpowers   } else if (magDiff > 0) {
8005697Smcpowers     MP_CHECKOK( s_mp_sub_3arg(a, b, c) );
8015697Smcpowers   } else {
8025697Smcpowers     MP_CHECKOK( s_mp_sub_3arg(b, a, c) );
8035697Smcpowers     MP_SIGN(c) = !MP_SIGN(a);
8045697Smcpowers   }
8055697Smcpowers 
8065697Smcpowers   if (s_mp_cmp_d(c, 0) == MP_EQ)
8075697Smcpowers     MP_SIGN(c) = MP_ZPOS;
8085697Smcpowers 
8095697Smcpowers CLEANUP:
8105697Smcpowers   return res;
8115697Smcpowers 
8125697Smcpowers } /* end mp_sub() */
8135697Smcpowers 
8145697Smcpowers /* }}} */
8155697Smcpowers 
8165697Smcpowers /* {{{ mp_mul(a, b, c) */
8175697Smcpowers 
8185697Smcpowers /*
8195697Smcpowers   mp_mul(a, b, c)
8205697Smcpowers 
8215697Smcpowers   Compute c = a * b.  All parameters may be identical.
8225697Smcpowers  */
mp_mul(const mp_int * a,const mp_int * b,mp_int * c)8235697Smcpowers mp_err   mp_mul(const mp_int *a, const mp_int *b, mp_int * c)
8245697Smcpowers {
8255697Smcpowers   mp_digit *pb;
8265697Smcpowers   mp_int   tmp;
8275697Smcpowers   mp_err   res;
8285697Smcpowers   mp_size  ib;
8295697Smcpowers   mp_size  useda, usedb;
8305697Smcpowers 
8315697Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
8325697Smcpowers 
8335697Smcpowers   if (a == c) {
8345697Smcpowers     if ((res = mp_init_copy(&tmp, a)) != MP_OKAY)
8355697Smcpowers       return res;
8365697Smcpowers     if (a == b)
8375697Smcpowers       b = &tmp;
8385697Smcpowers     a = &tmp;
8395697Smcpowers   } else if (b == c) {
8405697Smcpowers     if ((res = mp_init_copy(&tmp, b)) != MP_OKAY)
8415697Smcpowers       return res;
8425697Smcpowers     b = &tmp;
8435697Smcpowers   } else {
8445697Smcpowers     MP_DIGITS(&tmp) = 0;
8455697Smcpowers   }
8465697Smcpowers 
8475697Smcpowers   if (MP_USED(a) < MP_USED(b)) {
8485697Smcpowers     const mp_int *xch = b;	/* switch a and b, to do fewer outer loops */
8495697Smcpowers     b = a;
8505697Smcpowers     a = xch;
8515697Smcpowers   }
8525697Smcpowers 
8535697Smcpowers   MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
8545697Smcpowers   if((res = s_mp_pad(c, USED(a) + USED(b))) != MP_OKAY)
8555697Smcpowers     goto CLEANUP;
8565697Smcpowers 
8575697Smcpowers #ifdef NSS_USE_COMBA
8585697Smcpowers   if ((MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) {
8595697Smcpowers       if (MP_USED(a) == 4) {
8605697Smcpowers           s_mp_mul_comba_4(a, b, c);
8615697Smcpowers           goto CLEANUP;
8625697Smcpowers       }
8635697Smcpowers       if (MP_USED(a) == 8) {
8645697Smcpowers           s_mp_mul_comba_8(a, b, c);
8655697Smcpowers           goto CLEANUP;
8665697Smcpowers       }
8675697Smcpowers       if (MP_USED(a) == 16) {
8685697Smcpowers           s_mp_mul_comba_16(a, b, c);
8695697Smcpowers           goto CLEANUP;
8705697Smcpowers       }
8715697Smcpowers       if (MP_USED(a) == 32) {
8725697Smcpowers           s_mp_mul_comba_32(a, b, c);
8735697Smcpowers           goto CLEANUP;
8745697Smcpowers       }
8755697Smcpowers   }
8765697Smcpowers #endif
8775697Smcpowers 
8785697Smcpowers   pb = MP_DIGITS(b);
8795697Smcpowers   s_mpv_mul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
8805697Smcpowers 
8815697Smcpowers   /* Outer loop:  Digits of b */
8825697Smcpowers   useda = MP_USED(a);
8835697Smcpowers   usedb = MP_USED(b);
8845697Smcpowers   for (ib = 1; ib < usedb; ib++) {
8855697Smcpowers     mp_digit b_i    = *pb++;
8865697Smcpowers 
8875697Smcpowers     /* Inner product:  Digits of a */
8885697Smcpowers     if (b_i)
8895697Smcpowers       s_mpv_mul_d_add(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
8905697Smcpowers     else
8915697Smcpowers       MP_DIGIT(c, ib + useda) = b_i;
8925697Smcpowers   }
8935697Smcpowers 
8945697Smcpowers   s_mp_clamp(c);
8955697Smcpowers 
8965697Smcpowers   if(SIGN(a) == SIGN(b) || s_mp_cmp_d(c, 0) == MP_EQ)
8975697Smcpowers     SIGN(c) = ZPOS;
8985697Smcpowers   else
8995697Smcpowers     SIGN(c) = NEG;
9005697Smcpowers 
9015697Smcpowers CLEANUP:
9025697Smcpowers   mp_clear(&tmp);
9035697Smcpowers   return res;
9045697Smcpowers } /* end mp_mul() */
9055697Smcpowers 
9065697Smcpowers /* }}} */
9075697Smcpowers 
9085697Smcpowers /* {{{ mp_sqr(a, sqr) */
9095697Smcpowers 
9105697Smcpowers #if MP_SQUARE
9115697Smcpowers /*
9125697Smcpowers   Computes the square of a.  This can be done more
9135697Smcpowers   efficiently than a general multiplication, because many of the
9145697Smcpowers   computation steps are redundant when squaring.  The inner product
9155697Smcpowers   step is a bit more complicated, but we save a fair number of
9165697Smcpowers   iterations of the multiplication loop.
9175697Smcpowers  */
9185697Smcpowers 
9195697Smcpowers /* sqr = a^2;   Caller provides both a and tmp; */
mp_sqr(const mp_int * a,mp_int * sqr)9205697Smcpowers mp_err   mp_sqr(const mp_int *a, mp_int *sqr)
9215697Smcpowers {
9225697Smcpowers   mp_digit *pa;
9235697Smcpowers   mp_digit d;
9245697Smcpowers   mp_err   res;
9255697Smcpowers   mp_size  ix;
9265697Smcpowers   mp_int   tmp;
9275697Smcpowers   int      count;
9285697Smcpowers 
9295697Smcpowers   ARGCHK(a != NULL && sqr != NULL, MP_BADARG);
9305697Smcpowers 
9315697Smcpowers   if (a == sqr) {
9325697Smcpowers     if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
9335697Smcpowers       return res;
9345697Smcpowers     a = &tmp;
9355697Smcpowers   } else {
9365697Smcpowers     DIGITS(&tmp) = 0;
9375697Smcpowers     res = MP_OKAY;
9385697Smcpowers   }
9395697Smcpowers 
9405697Smcpowers   ix = 2 * MP_USED(a);
9415697Smcpowers   if (ix > MP_ALLOC(sqr)) {
9425697Smcpowers     MP_USED(sqr) = 1;
9435697Smcpowers     MP_CHECKOK( s_mp_grow(sqr, ix) );
9445697Smcpowers   }
9455697Smcpowers   MP_USED(sqr) = ix;
9465697Smcpowers   MP_DIGIT(sqr, 0) = 0;
9475697Smcpowers 
9485697Smcpowers #ifdef NSS_USE_COMBA
9495697Smcpowers   if (IS_POWER_OF_2(MP_USED(a))) {
9505697Smcpowers       if (MP_USED(a) == 4) {
9515697Smcpowers           s_mp_sqr_comba_4(a, sqr);
9525697Smcpowers           goto CLEANUP;
9535697Smcpowers       }
9545697Smcpowers       if (MP_USED(a) == 8) {
9555697Smcpowers           s_mp_sqr_comba_8(a, sqr);
9565697Smcpowers           goto CLEANUP;
9575697Smcpowers       }
9585697Smcpowers       if (MP_USED(a) == 16) {
9595697Smcpowers           s_mp_sqr_comba_16(a, sqr);
9605697Smcpowers           goto CLEANUP;
9615697Smcpowers       }
9625697Smcpowers       if (MP_USED(a) == 32) {
9635697Smcpowers           s_mp_sqr_comba_32(a, sqr);
9645697Smcpowers           goto CLEANUP;
9655697Smcpowers       }
9665697Smcpowers   }
9675697Smcpowers #endif
9685697Smcpowers 
9695697Smcpowers   pa = MP_DIGITS(a);
9705697Smcpowers   count = MP_USED(a) - 1;
9715697Smcpowers   if (count > 0) {
9725697Smcpowers     d = *pa++;
9735697Smcpowers     s_mpv_mul_d(pa, count, d, MP_DIGITS(sqr) + 1);
9745697Smcpowers     for (ix = 3; --count > 0; ix += 2) {
9755697Smcpowers       d = *pa++;
9765697Smcpowers       s_mpv_mul_d_add(pa, count, d, MP_DIGITS(sqr) + ix);
9775697Smcpowers     } /* for(ix ...) */
9785697Smcpowers     MP_DIGIT(sqr, MP_USED(sqr)-1) = 0; /* above loop stopped short of this. */
9795697Smcpowers 
9805697Smcpowers     /* now sqr *= 2 */
9815697Smcpowers     s_mp_mul_2(sqr);
9825697Smcpowers   } else {
9835697Smcpowers     MP_DIGIT(sqr, 1) = 0;
9845697Smcpowers   }
9855697Smcpowers 
9865697Smcpowers   /* now add the squares of the digits of a to sqr. */
9875697Smcpowers   s_mpv_sqr_add_prop(MP_DIGITS(a), MP_USED(a), MP_DIGITS(sqr));
9885697Smcpowers 
9895697Smcpowers   SIGN(sqr) = ZPOS;
9905697Smcpowers   s_mp_clamp(sqr);
9915697Smcpowers 
9925697Smcpowers CLEANUP:
9935697Smcpowers   mp_clear(&tmp);
9945697Smcpowers   return res;
9955697Smcpowers 
9965697Smcpowers } /* end mp_sqr() */
9975697Smcpowers #endif
9985697Smcpowers 
9995697Smcpowers /* }}} */
10005697Smcpowers 
10015697Smcpowers /* {{{ mp_div(a, b, q, r) */
10025697Smcpowers 
10035697Smcpowers /*
10045697Smcpowers   mp_div(a, b, q, r)
10055697Smcpowers 
10065697Smcpowers   Compute q = a / b and r = a mod b.  Input parameters may be re-used
10075697Smcpowers   as output parameters.  If q or r is NULL, that portion of the
10085697Smcpowers   computation will be discarded (although it will still be computed)
10095697Smcpowers  */
mp_div(const mp_int * a,const mp_int * b,mp_int * q,mp_int * r)10105697Smcpowers mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r)
10115697Smcpowers {
10125697Smcpowers   mp_err   res;
10135697Smcpowers   mp_int   *pQ, *pR;
10145697Smcpowers   mp_int   qtmp, rtmp, btmp;
10155697Smcpowers   int      cmp;
10165697Smcpowers   mp_sign  signA;
10175697Smcpowers   mp_sign  signB;
10185697Smcpowers 
10195697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
10205697Smcpowers 
10215697Smcpowers   signA = MP_SIGN(a);
10225697Smcpowers   signB = MP_SIGN(b);
10235697Smcpowers 
10245697Smcpowers   if(mp_cmp_z(b) == MP_EQ)
10255697Smcpowers     return MP_RANGE;
10265697Smcpowers 
10275697Smcpowers   DIGITS(&qtmp) = 0;
10285697Smcpowers   DIGITS(&rtmp) = 0;
10295697Smcpowers   DIGITS(&btmp) = 0;
10305697Smcpowers 
10315697Smcpowers   /* Set up some temporaries... */
10325697Smcpowers   if (!r || r == a || r == b) {
10335697Smcpowers     MP_CHECKOK( mp_init_copy(&rtmp, a) );
10345697Smcpowers     pR = &rtmp;
10355697Smcpowers   } else {
10365697Smcpowers     MP_CHECKOK( mp_copy(a, r) );
10375697Smcpowers     pR = r;
10385697Smcpowers   }
10395697Smcpowers 
10405697Smcpowers   if (!q || q == a || q == b) {
10415697Smcpowers     MP_CHECKOK( mp_init_size(&qtmp, MP_USED(a), FLAG(a)) );
10425697Smcpowers     pQ = &qtmp;
10435697Smcpowers   } else {
10445697Smcpowers     MP_CHECKOK( s_mp_pad(q, MP_USED(a)) );
10455697Smcpowers     pQ = q;
10465697Smcpowers     mp_zero(pQ);
10475697Smcpowers   }
10485697Smcpowers 
10495697Smcpowers   /*
10505697Smcpowers     If |a| <= |b|, we can compute the solution without division;
10515697Smcpowers     otherwise, we actually do the work required.
10525697Smcpowers    */
10535697Smcpowers   if ((cmp = s_mp_cmp(a, b)) <= 0) {
10545697Smcpowers     if (cmp) {
10555697Smcpowers       /* r was set to a above. */
10565697Smcpowers       mp_zero(pQ);
10575697Smcpowers     } else {
10585697Smcpowers       mp_set(pQ, 1);
10595697Smcpowers       mp_zero(pR);
10605697Smcpowers     }
10615697Smcpowers   } else {
10625697Smcpowers     MP_CHECKOK( mp_init_copy(&btmp, b) );
10635697Smcpowers     MP_CHECKOK( s_mp_div(pR, &btmp, pQ) );
10645697Smcpowers   }
10655697Smcpowers 
10665697Smcpowers   /* Compute the signs for the output  */
10675697Smcpowers   MP_SIGN(pR) = signA;   /* Sr = Sa              */
10685697Smcpowers   /* Sq = ZPOS if Sa == Sb */ /* Sq = NEG if Sa != Sb */
10695697Smcpowers   MP_SIGN(pQ) = (signA == signB) ? ZPOS : NEG;
10705697Smcpowers 
10715697Smcpowers   if(s_mp_cmp_d(pQ, 0) == MP_EQ)
10725697Smcpowers     SIGN(pQ) = ZPOS;
10735697Smcpowers   if(s_mp_cmp_d(pR, 0) == MP_EQ)
10745697Smcpowers     SIGN(pR) = ZPOS;
10755697Smcpowers 
10765697Smcpowers   /* Copy output, if it is needed      */
10775697Smcpowers   if(q && q != pQ)
10785697Smcpowers     s_mp_exch(pQ, q);
10795697Smcpowers 
10805697Smcpowers   if(r && r != pR)
10815697Smcpowers     s_mp_exch(pR, r);
10825697Smcpowers 
10835697Smcpowers CLEANUP:
10845697Smcpowers   mp_clear(&btmp);
10855697Smcpowers   mp_clear(&rtmp);
10865697Smcpowers   mp_clear(&qtmp);
10875697Smcpowers 
10885697Smcpowers   return res;
10895697Smcpowers 
10905697Smcpowers } /* end mp_div() */
10915697Smcpowers 
10925697Smcpowers /* }}} */
10935697Smcpowers 
10945697Smcpowers /* {{{ mp_div_2d(a, d, q, r) */
10955697Smcpowers 
mp_div_2d(const mp_int * a,mp_digit d,mp_int * q,mp_int * r)10965697Smcpowers mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r)
10975697Smcpowers {
10985697Smcpowers   mp_err  res;
10995697Smcpowers 
11005697Smcpowers   ARGCHK(a != NULL, MP_BADARG);
11015697Smcpowers 
11025697Smcpowers   if(q) {
11035697Smcpowers     if((res = mp_copy(a, q)) != MP_OKAY)
11045697Smcpowers       return res;
11055697Smcpowers   }
11065697Smcpowers   if(r) {
11075697Smcpowers     if((res = mp_copy(a, r)) != MP_OKAY)
11085697Smcpowers       return res;
11095697Smcpowers   }
11105697Smcpowers   if(q) {
11115697Smcpowers     s_mp_div_2d(q, d);
11125697Smcpowers   }
11135697Smcpowers   if(r) {
11145697Smcpowers     s_mp_mod_2d(r, d);
11155697Smcpowers   }
11165697Smcpowers 
11175697Smcpowers   return MP_OKAY;
11185697Smcpowers 
11195697Smcpowers } /* end mp_div_2d() */
11205697Smcpowers 
11215697Smcpowers /* }}} */
11225697Smcpowers 
11235697Smcpowers /* {{{ mp_expt(a, b, c) */
11245697Smcpowers 
11255697Smcpowers /*
11265697Smcpowers   mp_expt(a, b, c)
11275697Smcpowers 
11285697Smcpowers   Compute c = a ** b, that is, raise a to the b power.  Uses a
11295697Smcpowers   standard iterative square-and-multiply technique.
11305697Smcpowers  */
11315697Smcpowers 
mp_expt(mp_int * a,mp_int * b,mp_int * c)11325697Smcpowers mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c)
11335697Smcpowers {
11345697Smcpowers   mp_int   s, x;
11355697Smcpowers   mp_err   res;
11365697Smcpowers   mp_digit d;
11375697Smcpowers   int      dig, bit;
11385697Smcpowers 
11395697Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
11405697Smcpowers 
11415697Smcpowers   if(mp_cmp_z(b) < 0)
11425697Smcpowers     return MP_RANGE;
11435697Smcpowers 
11445697Smcpowers   if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
11455697Smcpowers     return res;
11465697Smcpowers 
11475697Smcpowers   mp_set(&s, 1);
11485697Smcpowers 
11495697Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY)
11505697Smcpowers     goto X;
11515697Smcpowers 
11525697Smcpowers   /* Loop over low-order digits in ascending order */
11535697Smcpowers   for(dig = 0; dig < (USED(b) - 1); dig++) {
11545697Smcpowers     d = DIGIT(b, dig);
11555697Smcpowers 
11565697Smcpowers     /* Loop over bits of each non-maximal digit */
11575697Smcpowers     for(bit = 0; bit < DIGIT_BIT; bit++) {
11585697Smcpowers       if(d & 1) {
11595697Smcpowers 	if((res = s_mp_mul(&s, &x)) != MP_OKAY)
11605697Smcpowers 	  goto CLEANUP;
11615697Smcpowers       }
11625697Smcpowers 
11635697Smcpowers       d >>= 1;
11645697Smcpowers 
11655697Smcpowers       if((res = s_mp_sqr(&x)) != MP_OKAY)
11665697Smcpowers 	goto CLEANUP;
11675697Smcpowers     }
11685697Smcpowers   }
11695697Smcpowers 
11705697Smcpowers   /* Consider now the last digit... */
11715697Smcpowers   d = DIGIT(b, dig);
11725697Smcpowers 
11735697Smcpowers   while(d) {
11745697Smcpowers     if(d & 1) {
11755697Smcpowers       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
11765697Smcpowers 	goto CLEANUP;
11775697Smcpowers     }
11785697Smcpowers 
11795697Smcpowers     d >>= 1;
11805697Smcpowers 
11815697Smcpowers     if((res = s_mp_sqr(&x)) != MP_OKAY)
11825697Smcpowers       goto CLEANUP;
11835697Smcpowers   }
11845697Smcpowers 
11855697Smcpowers   if(mp_iseven(b))
11865697Smcpowers     SIGN(&s) = SIGN(a);
11875697Smcpowers 
11885697Smcpowers   res = mp_copy(&s, c);
11895697Smcpowers 
11905697Smcpowers CLEANUP:
11915697Smcpowers   mp_clear(&x);
11925697Smcpowers X:
11935697Smcpowers   mp_clear(&s);
11945697Smcpowers 
11955697Smcpowers   return res;
11965697Smcpowers 
11975697Smcpowers } /* end mp_expt() */
11985697Smcpowers 
11995697Smcpowers /* }}} */
12005697Smcpowers 
12015697Smcpowers /* {{{ mp_2expt(a, k) */
12025697Smcpowers 
12035697Smcpowers /* Compute a = 2^k */
12045697Smcpowers 
mp_2expt(mp_int * a,mp_digit k)12055697Smcpowers mp_err mp_2expt(mp_int *a, mp_digit k)
12065697Smcpowers {
12075697Smcpowers   ARGCHK(a != NULL, MP_BADARG);
12085697Smcpowers 
12095697Smcpowers   return s_mp_2expt(a, k);
12105697Smcpowers 
12115697Smcpowers } /* end mp_2expt() */
12125697Smcpowers 
12135697Smcpowers /* }}} */
12145697Smcpowers 
12155697Smcpowers /* {{{ mp_mod(a, m, c) */
12165697Smcpowers 
12175697Smcpowers /*
12185697Smcpowers   mp_mod(a, m, c)
12195697Smcpowers 
12205697Smcpowers   Compute c = a (mod m).  Result will always be 0 <= c < m.
12215697Smcpowers  */
12225697Smcpowers 
mp_mod(const mp_int * a,const mp_int * m,mp_int * c)12235697Smcpowers mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c)
12245697Smcpowers {
12255697Smcpowers   mp_err  res;
12265697Smcpowers   int     mag;
12275697Smcpowers 
12285697Smcpowers   ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
12295697Smcpowers 
12305697Smcpowers   if(SIGN(m) == NEG)
12315697Smcpowers     return MP_RANGE;
12325697Smcpowers 
12335697Smcpowers   /*
12345697Smcpowers      If |a| > m, we need to divide to get the remainder and take the
12355697Smcpowers      absolute value.
12365697Smcpowers 
12375697Smcpowers      If |a| < m, we don't need to do any division, just copy and adjust
12385697Smcpowers      the sign (if a is negative).
12395697Smcpowers 
12405697Smcpowers      If |a| == m, we can simply set the result to zero.
12415697Smcpowers 
12425697Smcpowers      This order is intended to minimize the average path length of the
12435697Smcpowers      comparison chain on common workloads -- the most frequent cases are
12445697Smcpowers      that |a| != m, so we do those first.
12455697Smcpowers    */
12465697Smcpowers   if((mag = s_mp_cmp(a, m)) > 0) {
12475697Smcpowers     if((res = mp_div(a, m, NULL, c)) != MP_OKAY)
12485697Smcpowers       return res;
12495697Smcpowers 
12505697Smcpowers     if(SIGN(c) == NEG) {
12515697Smcpowers       if((res = mp_add(c, m, c)) != MP_OKAY)
12525697Smcpowers 	return res;
12535697Smcpowers     }
12545697Smcpowers 
12555697Smcpowers   } else if(mag < 0) {
12565697Smcpowers     if((res = mp_copy(a, c)) != MP_OKAY)
12575697Smcpowers       return res;
12585697Smcpowers 
12595697Smcpowers     if(mp_cmp_z(a) < 0) {
12605697Smcpowers       if((res = mp_add(c, m, c)) != MP_OKAY)
12615697Smcpowers 	return res;
12625697Smcpowers 
12635697Smcpowers     }
12645697Smcpowers 
12655697Smcpowers   } else {
12665697Smcpowers     mp_zero(c);
12675697Smcpowers 
12685697Smcpowers   }
12695697Smcpowers 
12705697Smcpowers   return MP_OKAY;
12715697Smcpowers 
12725697Smcpowers } /* end mp_mod() */
12735697Smcpowers 
12745697Smcpowers /* }}} */
12755697Smcpowers 
12765697Smcpowers /* {{{ mp_mod_d(a, d, c) */
12775697Smcpowers 
12785697Smcpowers /*
12795697Smcpowers   mp_mod_d(a, d, c)
12805697Smcpowers 
12815697Smcpowers   Compute c = a (mod d).  Result will always be 0 <= c < d
12825697Smcpowers  */
mp_mod_d(const mp_int * a,mp_digit d,mp_digit * c)12835697Smcpowers mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c)
12845697Smcpowers {
12855697Smcpowers   mp_err   res;
12865697Smcpowers   mp_digit rem;
12875697Smcpowers 
12885697Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
12895697Smcpowers 
12905697Smcpowers   if(s_mp_cmp_d(a, d) > 0) {
12915697Smcpowers     if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)
12925697Smcpowers       return res;
12935697Smcpowers 
12945697Smcpowers   } else {
12955697Smcpowers     if(SIGN(a) == NEG)
12965697Smcpowers       rem = d - DIGIT(a, 0);
12975697Smcpowers     else
12985697Smcpowers       rem = DIGIT(a, 0);
12995697Smcpowers   }
13005697Smcpowers 
13015697Smcpowers   if(c)
13025697Smcpowers     *c = rem;
13035697Smcpowers 
13045697Smcpowers   return MP_OKAY;
13055697Smcpowers 
13065697Smcpowers } /* end mp_mod_d() */
13075697Smcpowers 
13085697Smcpowers /* }}} */
13095697Smcpowers 
13105697Smcpowers /* {{{ mp_sqrt(a, b) */
13115697Smcpowers 
13125697Smcpowers /*
13135697Smcpowers   mp_sqrt(a, b)
13145697Smcpowers 
13155697Smcpowers   Compute the integer square root of a, and store the result in b.
13165697Smcpowers   Uses an integer-arithmetic version of Newton's iterative linear
13175697Smcpowers   approximation technique to determine this value; the result has the
13185697Smcpowers   following two properties:
13195697Smcpowers 
13205697Smcpowers      b^2 <= a
13215697Smcpowers      (b+1)^2 >= a
13225697Smcpowers 
13235697Smcpowers   It is a range error to pass a negative value.
13245697Smcpowers  */
mp_sqrt(const mp_int * a,mp_int * b)13255697Smcpowers mp_err mp_sqrt(const mp_int *a, mp_int *b)
13265697Smcpowers {
13275697Smcpowers   mp_int   x, t;
13285697Smcpowers   mp_err   res;
13295697Smcpowers   mp_size  used;
13305697Smcpowers 
13315697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_BADARG);
13325697Smcpowers 
13335697Smcpowers   /* Cannot take square root of a negative value */
13345697Smcpowers   if(SIGN(a) == NEG)
13355697Smcpowers     return MP_RANGE;
13365697Smcpowers 
13375697Smcpowers   /* Special cases for zero and one, trivial     */
13385697Smcpowers   if(mp_cmp_d(a, 1) <= 0)
13395697Smcpowers     return mp_copy(a, b);
13405697Smcpowers 
13415697Smcpowers   /* Initialize the temporaries we'll use below  */
13425697Smcpowers   if((res = mp_init_size(&t, USED(a), FLAG(a))) != MP_OKAY)
13435697Smcpowers     return res;
13445697Smcpowers 
13455697Smcpowers   /* Compute an initial guess for the iteration as a itself */
13465697Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY)
13475697Smcpowers     goto X;
13485697Smcpowers 
13495697Smcpowers   used = MP_USED(&x);
13505697Smcpowers   if (used > 1) {
13515697Smcpowers     s_mp_rshd(&x, used / 2);
13525697Smcpowers   }
13535697Smcpowers 
13545697Smcpowers   for(;;) {
13555697Smcpowers     /* t = (x * x) - a */
13565697Smcpowers     mp_copy(&x, &t);      /* can't fail, t is big enough for original x */
13575697Smcpowers     if((res = mp_sqr(&t, &t)) != MP_OKAY ||
13585697Smcpowers        (res = mp_sub(&t, a, &t)) != MP_OKAY)
13595697Smcpowers       goto CLEANUP;
13605697Smcpowers 
13615697Smcpowers     /* t = t / 2x       */
13625697Smcpowers     s_mp_mul_2(&x);
13635697Smcpowers     if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)
13645697Smcpowers       goto CLEANUP;
13655697Smcpowers     s_mp_div_2(&x);
13665697Smcpowers 
13675697Smcpowers     /* Terminate the loop, if the quotient is zero */
13685697Smcpowers     if(mp_cmp_z(&t) == MP_EQ)
13695697Smcpowers       break;
13705697Smcpowers 
13715697Smcpowers     /* x = x - t       */
13725697Smcpowers     if((res = mp_sub(&x, &t, &x)) != MP_OKAY)
13735697Smcpowers       goto CLEANUP;
13745697Smcpowers 
13755697Smcpowers   }
13765697Smcpowers 
13775697Smcpowers   /* Copy result to output parameter */
13785697Smcpowers   mp_sub_d(&x, 1, &x);
13795697Smcpowers   s_mp_exch(&x, b);
13805697Smcpowers 
13815697Smcpowers  CLEANUP:
13825697Smcpowers   mp_clear(&x);
13835697Smcpowers  X:
13845697Smcpowers   mp_clear(&t);
13855697Smcpowers 
13865697Smcpowers   return res;
13875697Smcpowers 
13885697Smcpowers } /* end mp_sqrt() */
13895697Smcpowers 
13905697Smcpowers /* }}} */
13915697Smcpowers 
13925697Smcpowers /* }}} */
13935697Smcpowers 
13945697Smcpowers /*------------------------------------------------------------------------*/
13955697Smcpowers /* {{{ Modular arithmetic */
13965697Smcpowers 
13975697Smcpowers #if MP_MODARITH
13985697Smcpowers /* {{{ mp_addmod(a, b, m, c) */
13995697Smcpowers 
14005697Smcpowers /*
14015697Smcpowers   mp_addmod(a, b, m, c)
14025697Smcpowers 
14035697Smcpowers   Compute c = (a + b) mod m
14045697Smcpowers  */
14055697Smcpowers 
mp_addmod(const mp_int * a,const mp_int * b,const mp_int * m,mp_int * c)14065697Smcpowers mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
14075697Smcpowers {
14085697Smcpowers   mp_err  res;
14095697Smcpowers 
14105697Smcpowers   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
14115697Smcpowers 
14125697Smcpowers   if((res = mp_add(a, b, c)) != MP_OKAY)
14135697Smcpowers     return res;
14145697Smcpowers   if((res = mp_mod(c, m, c)) != MP_OKAY)
14155697Smcpowers     return res;
14165697Smcpowers 
14175697Smcpowers   return MP_OKAY;
14185697Smcpowers 
14195697Smcpowers }
14205697Smcpowers 
14215697Smcpowers /* }}} */
14225697Smcpowers 
14235697Smcpowers /* {{{ mp_submod(a, b, m, c) */
14245697Smcpowers 
14255697Smcpowers /*
14265697Smcpowers   mp_submod(a, b, m, c)
14275697Smcpowers 
14285697Smcpowers   Compute c = (a - b) mod m
14295697Smcpowers  */
14305697Smcpowers 
mp_submod(const mp_int * a,const mp_int * b,const mp_int * m,mp_int * c)14315697Smcpowers mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
14325697Smcpowers {
14335697Smcpowers   mp_err  res;
14345697Smcpowers 
14355697Smcpowers   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
14365697Smcpowers 
14375697Smcpowers   if((res = mp_sub(a, b, c)) != MP_OKAY)
14385697Smcpowers     return res;
14395697Smcpowers   if((res = mp_mod(c, m, c)) != MP_OKAY)
14405697Smcpowers     return res;
14415697Smcpowers 
14425697Smcpowers   return MP_OKAY;
14435697Smcpowers 
14445697Smcpowers }
14455697Smcpowers 
14465697Smcpowers /* }}} */
14475697Smcpowers 
14485697Smcpowers /* {{{ mp_mulmod(a, b, m, c) */
14495697Smcpowers 
14505697Smcpowers /*
14515697Smcpowers   mp_mulmod(a, b, m, c)
14525697Smcpowers 
14535697Smcpowers   Compute c = (a * b) mod m
14545697Smcpowers  */
14555697Smcpowers 
mp_mulmod(const mp_int * a,const mp_int * b,const mp_int * m,mp_int * c)14565697Smcpowers mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
14575697Smcpowers {
14585697Smcpowers   mp_err  res;
14595697Smcpowers 
14605697Smcpowers   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
14615697Smcpowers 
14625697Smcpowers   if((res = mp_mul(a, b, c)) != MP_OKAY)
14635697Smcpowers     return res;
14645697Smcpowers   if((res = mp_mod(c, m, c)) != MP_OKAY)
14655697Smcpowers     return res;
14665697Smcpowers 
14675697Smcpowers   return MP_OKAY;
14685697Smcpowers 
14695697Smcpowers }
14705697Smcpowers 
14715697Smcpowers /* }}} */
14725697Smcpowers 
14735697Smcpowers /* {{{ mp_sqrmod(a, m, c) */
14745697Smcpowers 
14755697Smcpowers #if MP_SQUARE
mp_sqrmod(const mp_int * a,const mp_int * m,mp_int * c)14765697Smcpowers mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c)
14775697Smcpowers {
14785697Smcpowers   mp_err  res;
14795697Smcpowers 
14805697Smcpowers   ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
14815697Smcpowers 
14825697Smcpowers   if((res = mp_sqr(a, c)) != MP_OKAY)
14835697Smcpowers     return res;
14845697Smcpowers   if((res = mp_mod(c, m, c)) != MP_OKAY)
14855697Smcpowers     return res;
14865697Smcpowers 
14875697Smcpowers   return MP_OKAY;
14885697Smcpowers 
14895697Smcpowers } /* end mp_sqrmod() */
14905697Smcpowers #endif
14915697Smcpowers 
14925697Smcpowers /* }}} */
14935697Smcpowers 
14945697Smcpowers /* {{{ s_mp_exptmod(a, b, m, c) */
14955697Smcpowers 
14965697Smcpowers /*
14975697Smcpowers   s_mp_exptmod(a, b, m, c)
14985697Smcpowers 
14995697Smcpowers   Compute c = (a ** b) mod m.  Uses a standard square-and-multiply
15005697Smcpowers   method with modular reductions at each step. (This is basically the
15015697Smcpowers   same code as mp_expt(), except for the addition of the reductions)
15025697Smcpowers 
15035697Smcpowers   The modular reductions are done using Barrett's algorithm (see
15045697Smcpowers   s_mp_reduce() below for details)
15055697Smcpowers  */
15065697Smcpowers 
s_mp_exptmod(const mp_int * a,const mp_int * b,const mp_int * m,mp_int * c)15075697Smcpowers mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
15085697Smcpowers {
15095697Smcpowers   mp_int   s, x, mu;
15105697Smcpowers   mp_err   res;
15115697Smcpowers   mp_digit d;
15125697Smcpowers   int      dig, bit;
15135697Smcpowers 
15145697Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
15155697Smcpowers 
15165697Smcpowers   if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
15175697Smcpowers     return MP_RANGE;
15185697Smcpowers 
15195697Smcpowers   if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
15205697Smcpowers     return res;
15215697Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY ||
15225697Smcpowers      (res = mp_mod(&x, m, &x)) != MP_OKAY)
15235697Smcpowers     goto X;
15245697Smcpowers   if((res = mp_init(&mu, FLAG(a))) != MP_OKAY)
15255697Smcpowers     goto MU;
15265697Smcpowers 
15275697Smcpowers   mp_set(&s, 1);
15285697Smcpowers 
15295697Smcpowers   /* mu = b^2k / m */
15305697Smcpowers   s_mp_add_d(&mu, 1);
15315697Smcpowers   s_mp_lshd(&mu, 2 * USED(m));
15325697Smcpowers   if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)
15335697Smcpowers     goto CLEANUP;
15345697Smcpowers 
15355697Smcpowers   /* Loop over digits of b in ascending order, except highest order */
15365697Smcpowers   for(dig = 0; dig < (USED(b) - 1); dig++) {
15375697Smcpowers     d = DIGIT(b, dig);
15385697Smcpowers 
15395697Smcpowers     /* Loop over the bits of the lower-order digits */
15405697Smcpowers     for(bit = 0; bit < DIGIT_BIT; bit++) {
15415697Smcpowers       if(d & 1) {
15425697Smcpowers 	if((res = s_mp_mul(&s, &x)) != MP_OKAY)
15435697Smcpowers 	  goto CLEANUP;
15445697Smcpowers 	if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
15455697Smcpowers 	  goto CLEANUP;
15465697Smcpowers       }
15475697Smcpowers 
15485697Smcpowers       d >>= 1;
15495697Smcpowers 
15505697Smcpowers       if((res = s_mp_sqr(&x)) != MP_OKAY)
15515697Smcpowers 	goto CLEANUP;
15525697Smcpowers       if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
15535697Smcpowers 	goto CLEANUP;
15545697Smcpowers     }
15555697Smcpowers   }
15565697Smcpowers 
15575697Smcpowers   /* Now do the last digit... */
15585697Smcpowers   d = DIGIT(b, dig);
15595697Smcpowers 
15605697Smcpowers   while(d) {
15615697Smcpowers     if(d & 1) {
15625697Smcpowers       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
15635697Smcpowers 	goto CLEANUP;
15645697Smcpowers       if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
15655697Smcpowers 	goto CLEANUP;
15665697Smcpowers     }
15675697Smcpowers 
15685697Smcpowers     d >>= 1;
15695697Smcpowers 
15705697Smcpowers     if((res = s_mp_sqr(&x)) != MP_OKAY)
15715697Smcpowers       goto CLEANUP;
15725697Smcpowers     if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
15735697Smcpowers       goto CLEANUP;
15745697Smcpowers   }
15755697Smcpowers 
15765697Smcpowers   s_mp_exch(&s, c);
15775697Smcpowers 
15785697Smcpowers  CLEANUP:
15795697Smcpowers   mp_clear(&mu);
15805697Smcpowers  MU:
15815697Smcpowers   mp_clear(&x);
15825697Smcpowers  X:
15835697Smcpowers   mp_clear(&s);
15845697Smcpowers 
15855697Smcpowers   return res;
15865697Smcpowers 
15875697Smcpowers } /* end s_mp_exptmod() */
15885697Smcpowers 
15895697Smcpowers /* }}} */
15905697Smcpowers 
15915697Smcpowers /* {{{ mp_exptmod_d(a, d, m, c) */
15925697Smcpowers 
mp_exptmod_d(const mp_int * a,mp_digit d,const mp_int * m,mp_int * c)15935697Smcpowers mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c)
15945697Smcpowers {
15955697Smcpowers   mp_int   s, x;
15965697Smcpowers   mp_err   res;
15975697Smcpowers 
15985697Smcpowers   ARGCHK(a != NULL && c != NULL, MP_BADARG);
15995697Smcpowers 
16005697Smcpowers   if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
16015697Smcpowers     return res;
16025697Smcpowers   if((res = mp_init_copy(&x, a)) != MP_OKAY)
16035697Smcpowers     goto X;
16045697Smcpowers 
16055697Smcpowers   mp_set(&s, 1);
16065697Smcpowers 
16075697Smcpowers   while(d != 0) {
16085697Smcpowers     if(d & 1) {
16095697Smcpowers       if((res = s_mp_mul(&s, &x)) != MP_OKAY ||
16105697Smcpowers 	 (res = mp_mod(&s, m, &s)) != MP_OKAY)
16115697Smcpowers 	goto CLEANUP;
16125697Smcpowers     }
16135697Smcpowers 
16145697Smcpowers     d /= 2;
16155697Smcpowers 
16165697Smcpowers     if((res = s_mp_sqr(&x)) != MP_OKAY ||
16175697Smcpowers        (res = mp_mod(&x, m, &x)) != MP_OKAY)
16185697Smcpowers       goto CLEANUP;
16195697Smcpowers   }
16205697Smcpowers 
16215697Smcpowers   s_mp_exch(&s, c);
16225697Smcpowers 
16235697Smcpowers CLEANUP:
16245697Smcpowers   mp_clear(&x);
16255697Smcpowers X:
16265697Smcpowers   mp_clear(&s);
16275697Smcpowers 
16285697Smcpowers   return res;
16295697Smcpowers 
16305697Smcpowers } /* end mp_exptmod_d() */
16315697Smcpowers 
16325697Smcpowers /* }}} */
16335697Smcpowers #endif /* if MP_MODARITH */
16345697Smcpowers 
16355697Smcpowers /* }}} */
16365697Smcpowers 
16375697Smcpowers /*------------------------------------------------------------------------*/
16385697Smcpowers /* {{{ Comparison functions */
16395697Smcpowers 
16405697Smcpowers /* {{{ mp_cmp_z(a) */
16415697Smcpowers 
16425697Smcpowers /*
16435697Smcpowers   mp_cmp_z(a)
16445697Smcpowers 
16455697Smcpowers   Compare a <=> 0.  Returns <0 if a<0, 0 if a=0, >0 if a>0.
16465697Smcpowers  */
16475697Smcpowers 
mp_cmp_z(const mp_int * a)16485697Smcpowers int    mp_cmp_z(const mp_int *a)
16495697Smcpowers {
16505697Smcpowers   if(SIGN(a) == NEG)
16515697Smcpowers     return MP_LT;
16525697Smcpowers   else if(USED(a) == 1 && DIGIT(a, 0) == 0)
16535697Smcpowers     return MP_EQ;
16545697Smcpowers   else
16555697Smcpowers     return MP_GT;
16565697Smcpowers 
16575697Smcpowers } /* end mp_cmp_z() */
16585697Smcpowers 
16595697Smcpowers /* }}} */
16605697Smcpowers 
16615697Smcpowers /* {{{ mp_cmp_d(a, d) */
16625697Smcpowers 
16635697Smcpowers /*
16645697Smcpowers   mp_cmp_d(a, d)
16655697Smcpowers 
16665697Smcpowers   Compare a <=> d.  Returns <0 if a<d, 0 if a=d, >0 if a>d
16675697Smcpowers  */
16685697Smcpowers 
mp_cmp_d(const mp_int * a,mp_digit d)16695697Smcpowers int    mp_cmp_d(const mp_int *a, mp_digit d)
16705697Smcpowers {
16715697Smcpowers   ARGCHK(a != NULL, MP_EQ);
16725697Smcpowers 
16735697Smcpowers   if(SIGN(a) == NEG)
16745697Smcpowers     return MP_LT;
16755697Smcpowers 
16765697Smcpowers   return s_mp_cmp_d(a, d);
16775697Smcpowers 
16785697Smcpowers } /* end mp_cmp_d() */
16795697Smcpowers 
16805697Smcpowers /* }}} */
16815697Smcpowers 
16825697Smcpowers /* {{{ mp_cmp(a, b) */
16835697Smcpowers 
mp_cmp(const mp_int * a,const mp_int * b)16845697Smcpowers int    mp_cmp(const mp_int *a, const mp_int *b)
16855697Smcpowers {
16865697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_EQ);
16875697Smcpowers 
16885697Smcpowers   if(SIGN(a) == SIGN(b)) {
16895697Smcpowers     int  mag;
16905697Smcpowers 
16915697Smcpowers     if((mag = s_mp_cmp(a, b)) == MP_EQ)
16925697Smcpowers       return MP_EQ;
16935697Smcpowers 
16945697Smcpowers     if(SIGN(a) == ZPOS)
16955697Smcpowers       return mag;
16965697Smcpowers     else
16975697Smcpowers       return -mag;
16985697Smcpowers 
16995697Smcpowers   } else if(SIGN(a) == ZPOS) {
17005697Smcpowers     return MP_GT;
17015697Smcpowers   } else {
17025697Smcpowers     return MP_LT;
17035697Smcpowers   }
17045697Smcpowers 
17055697Smcpowers } /* end mp_cmp() */
17065697Smcpowers 
17075697Smcpowers /* }}} */
17085697Smcpowers 
17095697Smcpowers /* {{{ mp_cmp_mag(a, b) */
17105697Smcpowers 
17115697Smcpowers /*
17125697Smcpowers   mp_cmp_mag(a, b)
17135697Smcpowers 
17145697Smcpowers   Compares |a| <=> |b|, and returns an appropriate comparison result
17155697Smcpowers  */
17165697Smcpowers 
mp_cmp_mag(mp_int * a,mp_int * b)17175697Smcpowers int    mp_cmp_mag(mp_int *a, mp_int *b)
17185697Smcpowers {
17195697Smcpowers   ARGCHK(a != NULL && b != NULL, MP_EQ);
17205697Smcpowers 
17215697Smcpowers   return s_mp_cmp(a, b);
17225697Smcpowers 
17235697Smcpowers } /* end mp_cmp_mag() */
17245697Smcpowers 
17255697Smcpowers /* }}} */
17265697Smcpowers 
17275697Smcpowers /* {{{ mp_cmp_int(a, z, kmflag) */
17285697Smcpowers 
17295697Smcpowers /*
17305697Smcpowers   This just converts z to an mp_int, and uses the existing comparison
17315697Smcpowers   routines.  This is sort of inefficient, but it's not clear to me how
17325697Smcpowers   frequently this wil get used anyway.  For small positive constants,
17335697Smcpowers   you can always use mp_cmp_d(), and for zero, there is mp_cmp_z().
17345697Smcpowers  */
mp_cmp_int(const mp_int * a,long z,int kmflag)17355697Smcpowers int    mp_cmp_int(const mp_int *a, long z, int kmflag)
17365697Smcpowers {
17375697Smcpowers   mp_int  tmp;
17385697Smcpowers   int     out;
17395697Smcpowers 
17405697Smcpowers   ARGCHK(a != NULL, MP_EQ);
17415697Smcpowers 
17425697Smcpowers   mp_init(&tmp, kmflag); mp_set_int(&tmp, z);
17435697Smcpowers   out = mp_cmp(a, &tmp);
17445697Smcpowers   mp_clear(&tmp);
17455697Smcpowers 
17465697Smcpowers   return out;
17475697Smcpowers 
17485697Smcpowers } /* end mp_cmp_int() */
17495697Smcpowers 
17505697Smcpowers /* }}} */
17515697Smcpowers 
17525697Smcpowers /* {{{ mp_isodd(a) */
17535697Smcpowers 
17545697Smcpowers /*
17555697Smcpowers   mp_isodd(a)
17565697Smcpowers 
17575697Smcpowers   Returns a true (non-zero) value if a is odd, false (zero) otherwise.
17585697Smcpowers  */
mp_isodd(const mp_int * a)17595697Smcpowers int    mp_isodd(const mp_int *a)
17605697Smcpowers {
17615697Smcpowers   ARGCHK(a != NULL, 0);
17625697Smcpowers 
17635697Smcpowers   return (int)(DIGIT(a, 0) & 1);
17645697Smcpowers 
17655697Smcpowers } /* end mp_isodd() */
17665697Smcpowers 
17675697Smcpowers /* }}} */
17685697Smcpowers 
17695697Smcpowers /* {{{ mp_iseven(a) */
17705697Smcpowers 
mp_iseven(const mp_int * a)17715697Smcpowers int    mp_iseven(const mp_int *a)
17725697Smcpowers {
17735697Smcpowers   return !mp_isodd(a);
17745697Smcpowers 
17755697Smcpowers } /* end mp_iseven() */
17765697Smcpowers 
17775697Smcpowers /* }}} */
17785697Smcpowers 
17795697Smcpowers /* }}} */
17805697Smcpowers 
17815697Smcpowers /*------------------------------------------------------------------------*/
17825697Smcpowers /* {{{ Number theoretic functions */
17835697Smcpowers 
17845697Smcpowers #if MP_NUMTH
17855697Smcpowers /* {{{ mp_gcd(a, b, c) */
17865697Smcpowers 
17875697Smcpowers /*
17885697Smcpowers   Like the old mp_gcd() function, except computes the GCD using the
17895697Smcpowers   binary algorithm due to Josef Stein in 1961 (via Knuth).
17905697Smcpowers  */
mp_gcd(mp_int * a,mp_int * b,mp_int * c)17915697Smcpowers mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c)
17925697Smcpowers {
17935697Smcpowers   mp_err   res;
17945697Smcpowers   mp_int   u, v, t;
17955697Smcpowers   mp_size  k = 0;
17965697Smcpowers 
17975697Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
17985697Smcpowers 
17995697Smcpowers   if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)
18005697Smcpowers       return MP_RANGE;
18015697Smcpowers   if(mp_cmp_z(a) == MP_EQ) {
18025697Smcpowers     return mp_copy(b, c);
18035697Smcpowers   } else if(mp_cmp_z(b) == MP_EQ) {
18045697Smcpowers     return mp_copy(a, c);
18055697Smcpowers   }
18065697Smcpowers 
18075697Smcpowers   if((res = mp_init(&t, FLAG(a))) != MP_OKAY)
18085697Smcpowers     return res;
18095697Smcpowers   if((res = mp_init_copy(&u, a)) != MP_OKAY)
18105697Smcpowers     goto U;
18115697Smcpowers   if((res = mp_init_copy(&v, b)) != MP_OKAY)
18125697Smcpowers     goto V;
18135697Smcpowers 
18145697Smcpowers   SIGN(&u) = ZPOS;
18155697Smcpowers   SIGN(&v) = ZPOS;
18165697Smcpowers 
18175697Smcpowers   /* Divide out common factors of 2 until at least 1 of a, b is even */
18185697Smcpowers   while(mp_iseven(&u) && mp_iseven(&v)) {
18195697Smcpowers     s_mp_div_2(&u);
18205697Smcpowers     s_mp_div_2(&v);
18215697Smcpowers     ++k;
18225697Smcpowers   }
18235697Smcpowers 
18245697Smcpowers   /* Initialize t */
18255697Smcpowers   if(mp_isodd(&u)) {
18265697Smcpowers     if((res = mp_copy(&v, &t)) != MP_OKAY)
18275697Smcpowers       goto CLEANUP;
18285697Smcpowers 
18295697Smcpowers     /* t = -v */
18305697Smcpowers     if(SIGN(&v) == ZPOS)
18315697Smcpowers       SIGN(&t) = NEG;
18325697Smcpowers     else
18335697Smcpowers       SIGN(&t) = ZPOS;
18345697Smcpowers 
18355697Smcpowers   } else {
18365697Smcpowers     if((res = mp_copy(&u, &t)) != MP_OKAY)
18375697Smcpowers       goto CLEANUP;
18385697Smcpowers 
18395697Smcpowers   }
18405697Smcpowers 
18415697Smcpowers   for(;;) {
18425697Smcpowers     while(mp_iseven(&t)) {
18435697Smcpowers       s_mp_div_2(&t);
18445697Smcpowers     }
18455697Smcpowers 
18465697Smcpowers     if(mp_cmp_z(&t) == MP_GT) {
18475697Smcpowers       if((res = mp_copy(&t, &u)) != MP_OKAY)
18485697Smcpowers 	goto CLEANUP;
18495697Smcpowers 
18505697Smcpowers     } else {
18515697Smcpowers       if((res = mp_copy(&t, &v)) != MP_OKAY)
18525697Smcpowers 	goto CLEANUP;
18535697Smcpowers 
18545697Smcpowers       /* v = -t */
18555697Smcpowers       if(SIGN(&t) == ZPOS)
18565697Smcpowers 	SIGN(&v) = NEG;
18575697Smcpowers       else
18585697Smcpowers 	SIGN(&v) = ZPOS;
18595697Smcpowers     }
18605697Smcpowers 
18615697Smcpowers     if((res = mp_sub(&u, &v, &t)) != MP_OKAY)
18625697Smcpowers       goto CLEANUP;
18635697Smcpowers 
18645697Smcpowers     if(s_mp_cmp_d(&t, 0) == MP_EQ)
18655697Smcpowers       break;
18665697Smcpowers   }
18675697Smcpowers 
18685697Smcpowers   s_mp_2expt(&v, k);       /* v = 2^k   */
18695697Smcpowers   res = mp_mul(&u, &v, c); /* c = u * v */
18705697Smcpowers 
18715697Smcpowers  CLEANUP:
18725697Smcpowers   mp_clear(&v);
18735697Smcpowers  V:
18745697Smcpowers   mp_clear(&u);
18755697Smcpowers  U:
18765697Smcpowers   mp_clear(&t);
18775697Smcpowers 
18785697Smcpowers   return res;
18795697Smcpowers 
18805697Smcpowers } /* end mp_gcd() */
18815697Smcpowers 
18825697Smcpowers /* }}} */
18835697Smcpowers 
18845697Smcpowers /* {{{ mp_lcm(a, b, c) */
18855697Smcpowers 
18865697Smcpowers /* We compute the least common multiple using the rule:
18875697Smcpowers 
18885697Smcpowers    ab = [a, b](a, b)
18895697Smcpowers 
18905697Smcpowers    ... by computing the product, and dividing out the gcd.
18915697Smcpowers  */
18925697Smcpowers 
mp_lcm(mp_int * a,mp_int * b,mp_int * c)18935697Smcpowers mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c)
18945697Smcpowers {
18955697Smcpowers   mp_int  gcd, prod;
18965697Smcpowers   mp_err  res;
18975697Smcpowers 
18985697Smcpowers   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
18995697Smcpowers 
19005697Smcpowers   /* Set up temporaries */
19015697Smcpowers   if((res = mp_init(&gcd, FLAG(a))) != MP_OKAY)
19025697Smcpowers     return res;
19035697Smcpowers   if((res = mp_init(&prod, FLAG(a))) != MP_OKAY)
19045697Smcpowers     goto GCD;
19055697Smcpowers 
19065697Smcpowers   if((res = mp_mul(a, b, &prod)) != MP_OKAY)
19075697Smcpowers     goto CLEANUP;
19085697Smcpowers   if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)
19095697Smcpowers     goto CLEANUP;
19105697Smcpowers 
19115697Smcpowers   res = mp_div(&prod, &gcd, c, NULL);
19125697Smcpowers 
19135697Smcpowers  CLEANUP:
19145697Smcpowers   mp_clear(&prod);
19155697Smcpowers  GCD:
19165697Smcpowers   mp_clear(&gcd);
19175697Smcpowers 
19185697Smcpowers   return res;
19195697Smcpowers 
19205697Smcpowers } /* end mp_lcm() */
19215697Smcpowers 
19225697Smcpowers /* }}} */
19235697Smcpowers 
19245697Smcpowers /* {{{ mp_xgcd(a, b, g, x, y) */
19255697Smcpowers 
19265697Smcpowers /*
19275697Smcpowers   mp_xgcd(a, b, g, x, y)
19285697Smcpowers 
19295697Smcpowers   Compute g = (a, b) and values x and y satisfying Bezout's identity
19305697Smcpowers   (that is, ax + by = g).  This uses the binary extended GCD algorithm
19315697Smcpowers   based on the Stein algorithm used for mp_gcd()
19325697Smcpowers   See algorithm 14.61 in Handbook of Applied Cryptogrpahy.
19335697Smcpowers  */
19345697Smcpowers 
mp_xgcd(const mp_int * a,const mp_int * b,mp_int * g,mp_int * x,mp_int * y)19355697Smcpowers mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y)
19365697Smcpowers {
19375697Smcpowers   mp_int   gx, xc, yc, u, v, A, B, C, D;
19385697Smcpowers   mp_int  *clean[9];
19395697Smcpowers   mp_err   res;
19405697Smcpowers   int      last = -1;
19415697Smcpowers 
19425697Smcpowers   if(mp_cmp_z(b) == 0)
19435697Smcpowers     return MP_RANGE;
19445697Smcpowers 
19455697Smcpowers   /* Initialize all these variables we need */
19465697Smcpowers   MP_CHECKOK( mp_init(&u, FLAG(a)) );
19475697Smcpowers   clean[++last] = &u;
19485697Smcpowers   MP_CHECKOK( mp_init(&v, FLAG(a)) );
19495697Smcpowers   clean[++last] = &v;
19505697Smcpowers   MP_CHECKOK( mp_init(&gx, FLAG(a)) );
19515697Smcpowers   clean[++last] = &gx;
19525697Smcpowers   MP_CHECKOK( mp_init(&A, FLAG(a)) );
19535697Smcpowers   clean[++last] = &A;
19545697Smcpowers   MP_CHECKOK( mp_init(&B, FLAG(a)) );
19555697Smcpowers   clean[++last] = &B;
19565697Smcpowers   MP_CHECKOK( mp_init(&C, FLAG(a)) );
19575697Smcpowers   clean[++last] = &C;
19585697Smcpowers   MP_CHECKOK( mp_init(&D, FLAG(a)) );
19595697Smcpowers   clean[++last] = &D;
19605697Smcpowers   MP_CHECKOK( mp_init_copy(&xc, a) );
19615697Smcpowers   clean[++last] = &xc;
19625697Smcpowers   mp_abs(&xc, &xc);
19635697Smcpowers   MP_CHECKOK( mp_init_copy(&yc, b) );
19645697Smcpowers   clean[++last] = &yc;
19655697Smcpowers   mp_abs(&yc, &yc);
19665697Smcpowers 
19675697Smcpowers   mp_set(&gx, 1);
19685697Smcpowers 
19695697Smcpowers   /* Divide by two until at least one of them is odd */
19705697Smcpowers   while(mp_iseven(&xc) && mp_iseven(&yc)) {
19715697Smcpowers     mp_size nx = mp_trailing_zeros(&xc);
19725697Smcpowers     mp_size ny = mp_trailing_zeros(&yc);
19735697Smcpowers     mp_size n  = MP_MIN(nx, ny);
19745697Smcpowers     s_mp_div_2d(&xc,n);
19755697Smcpowers     s_mp_div_2d(&yc,n);
19765697Smcpowers     MP_CHECKOK( s_mp_mul_2d(&gx,n) );
19775697Smcpowers   }
19785697Smcpowers 
19795697Smcpowers   mp_copy(&xc, &u);
19805697Smcpowers   mp_copy(&yc, &v);
19815697Smcpowers   mp_set(&A, 1); mp_set(&D, 1);
19825697Smcpowers 
19835697Smcpowers   /* Loop through binary GCD algorithm */
19845697Smcpowers   do {
19855697Smcpowers     while(mp_iseven(&u)) {
19865697Smcpowers       s_mp_div_2(&u);
19875697Smcpowers 
19885697Smcpowers       if(mp_iseven(&A) && mp_iseven(&B)) {
19895697Smcpowers 	s_mp_div_2(&A); s_mp_div_2(&B);
19905697Smcpowers       } else {
19915697Smcpowers 	MP_CHECKOK( mp_add(&A, &yc, &A) );
19925697Smcpowers 	s_mp_div_2(&A);
19935697Smcpowers 	MP_CHECKOK( mp_sub(&B, &xc, &B) );
19945697Smcpowers 	s_mp_div_2(&B);
19955697Smcpowers       }
19965697Smcpowers     }
19975697Smcpowers 
19985697Smcpowers     while(mp_iseven(&v)) {
19995697Smcpowers       s_mp_div_2(&v);
20005697Smcpowers 
20015697Smcpowers       if(mp_iseven(&C) && mp_iseven(&D)) {
20025697Smcpowers 	s_mp_div_2(&C); s_mp_div_2(&D);
20035697Smcpowers       } else {
20045697Smcpowers 	MP_CHECKOK( mp_add(&C, &yc, &C) );
20055697Smcpowers 	s_mp_div_2(&C);
20065697Smcpowers 	MP_CHECKOK( mp_sub(&D, &xc, &D) );
20075697Smcpowers 	s_mp_div_2(&D);
20085697Smcpowers       }
20095697Smcpowers     }
20105697Smcpowers 
20115697Smcpowers     if(mp_cmp(&u, &v) >= 0) {
20125697Smcpowers       MP_CHECKOK( mp_sub(&u, &v, &u) );
20135697Smcpowers       MP_CHECKOK( mp_sub(&A, &C, &A) );
20145697Smcpowers       MP_CHECKOK( mp_sub(&B, &D, &B) );
20155697Smcpowers     } else {
20165697Smcpowers       MP_CHECKOK( mp_sub(&v, &u, &v) );
20175697Smcpowers       MP_CHECKOK( mp_sub(&C, &A, &C) );
20185697Smcpowers       MP_CHECKOK( mp_sub(&D, &B, &D) );
20195697Smcpowers     }
20205697Smcpowers   } while (mp_cmp_z(&u) != 0);
20215697Smcpowers 
20225697Smcpowers   /* copy results to output */
20235697Smcpowers   if(x)
20245697Smcpowers     MP_CHECKOK( mp_copy(&C, x) );
20255697Smcpowers 
20265697Smcpowers   if(y)
20275697Smcpowers     MP_CHECKOK( mp_copy(&D, y) );
20285697Smcpowers 
20295697Smcpowers   if(g)
20305697Smcpowers     MP_CHECKOK( mp_mul(&gx, &v, g) );
20315697Smcpowers 
20325697Smcpowers  CLEANUP:
20335697Smcpowers   while(last >= 0)
20345697Smcpowers     mp_clear(clean[last--]);
20355697Smcpowers 
20365697Smcpowers   return res;
20375697Smcpowers 
20385697Smcpowers } /* end mp_xgcd() */
20395697Smcpowers 
20405697Smcpowers /* }}} */
20415697Smcpowers 
mp_trailing_zeros(const mp_int * mp)20425697Smcpowers mp_size mp_trailing_zeros(const mp_int *mp)
20435697Smcpowers {
20445697Smcpowers   mp_digit d;
20455697Smcpowers   mp_size  n = 0;
20465697Smcpowers   int      ix;
20475697Smcpowers 
20485697Smcpowers   if (!mp || !MP_DIGITS(mp) || !mp_cmp_z(mp))
20495697Smcpowers     return n;
20505697Smcpowers 
20515697Smcpowers   for (ix = 0; !(d = MP_DIGIT(mp,ix)) && (ix < MP_USED(mp)); ++ix)
20525697Smcpowers     n += MP_DIGIT_BIT;
20535697Smcpowers   if (!d)
20545697Smcpowers     return 0;	/* shouldn't happen, but ... */
20555697Smcpowers #if !defined(MP_USE_UINT_DIGIT)
20565697Smcpowers   if (!(d & 0xffffffffU)) {
20575697Smcpowers     d >>= 32;
20585697Smcpowers     n  += 32;
20595697Smcpowers   }
20605697Smcpowers #endif
20615697Smcpowers   if (!(d & 0xffffU)) {
20625697Smcpowers     d >>= 16;
20635697Smcpowers     n  += 16;
20645697Smcpowers   }
20655697Smcpowers   if (!(d & 0xffU)) {
20665697Smcpowers     d >>= 8;
20675697Smcpowers     n  += 8;
20685697Smcpowers   }
20695697Smcpowers   if (!(d & 0xfU)) {
20705697Smcpowers     d >>= 4;
20715697Smcpowers     n  += 4;
20725697Smcpowers   }
20735697Smcpowers   if (!(d & 0x3U)) {
20745697Smcpowers     d >>= 2;
20755697Smcpowers     n  += 2;
20765697Smcpowers   }
20775697Smcpowers   if (!(d & 0x1U)) {
20785697Smcpowers     d >>= 1;
20795697Smcpowers     n  += 1;
20805697Smcpowers   }
20815697Smcpowers #if MP_ARGCHK == 2
20825697Smcpowers   assert(0 != (d & 1));
20835697Smcpowers #endif
20845697Smcpowers   return n;
20855697Smcpowers }
20865697Smcpowers 
20875697Smcpowers /* Given a and prime p, computes c and k such that a*c == 2**k (mod p).
20885697Smcpowers ** Returns k (positive) or error (negative).
20895697Smcpowers ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
20905697Smcpowers ** by Richard Schroeppel (a.k.a. Captain Nemo).
20915697Smcpowers */
s_mp_almost_inverse(const mp_int * a,const mp_int * p,mp_int * c)20925697Smcpowers mp_err s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
20935697Smcpowers {
20945697Smcpowers   mp_err res;
20955697Smcpowers   mp_err k    = 0;
20965697Smcpowers   mp_int d, f, g;
20975697Smcpowers 
20985697Smcpowers   ARGCHK(a && p && c, MP_BADARG);
20995697Smcpowers 
21005697Smcpowers   MP_DIGITS(&d) = 0;
21015697Smcpowers   MP_DIGITS(&f) = 0;
21025697Smcpowers   MP_DIGITS(&g) = 0;
21035697Smcpowers   MP_CHECKOK( mp_init(&d, FLAG(a)) );
21045697Smcpowers   MP_CHECKOK( mp_init_copy(&f, a) );	/* f = a */
21055697Smcpowers   MP_CHECKOK( mp_init_copy(&g, p) );	/* g = p */
21065697Smcpowers 
21075697Smcpowers   mp_set(c, 1);
21085697Smcpowers   mp_zero(&d);
21095697Smcpowers 
21105697Smcpowers   if (mp_cmp_z(&f) == 0) {
21115697Smcpowers     res = MP_UNDEF;
21125697Smcpowers   } else
21135697Smcpowers   for (;;) {
21145697Smcpowers     int diff_sign;
21155697Smcpowers     while (mp_iseven(&f)) {
21165697Smcpowers       mp_size n = mp_trailing_zeros(&f);
21175697Smcpowers       if (!n) {
21185697Smcpowers 	res = MP_UNDEF;
21195697Smcpowers 	goto CLEANUP;
21205697Smcpowers       }
21215697Smcpowers       s_mp_div_2d(&f, n);
21225697Smcpowers       MP_CHECKOK( s_mp_mul_2d(&d, n) );
21235697Smcpowers       k += n;
21245697Smcpowers     }
21255697Smcpowers     if (mp_cmp_d(&f, 1) == MP_EQ) {	/* f == 1 */
21265697Smcpowers       res = k;
21275697Smcpowers       break;
21285697Smcpowers     }
21295697Smcpowers     diff_sign = mp_cmp(&f, &g);
21305697Smcpowers     if (diff_sign < 0) {		/* f < g */
21315697Smcpowers       s_mp_exch(&f, &g);
21325697Smcpowers       s_mp_exch(c, &d);
21335697Smcpowers     } else if (diff_sign == 0) {		/* f == g */
21345697Smcpowers       res = MP_UNDEF;		/* a and p are not relatively prime */
21355697Smcpowers       break;
21365697Smcpowers     }
21375697Smcpowers     if ((MP_DIGIT(&f,0) % 4) == (MP_DIGIT(&g,0) % 4)) {
21385697Smcpowers       MP_CHECKOK( mp_sub(&f, &g, &f) );	/* f = f - g */
21395697Smcpowers       MP_CHECKOK( mp_sub(c,  &d,  c) );	/* c = c - d */
21405697Smcpowers     } else {
21415697Smcpowers       MP_CHECKOK( mp_add(&f, &g, &f) );	/* f = f + g */
21425697Smcpowers       MP_CHECKOK( mp_add(c,  &d,  c) );	/* c = c + d */
21435697Smcpowers     }
21445697Smcpowers   }
21455697Smcpowers   if (res >= 0) {
21465697Smcpowers     while (MP_SIGN(c) != MP_ZPOS) {
21475697Smcpowers       MP_CHECKOK( mp_add(c, p, c) );
21485697Smcpowers     }
21495697Smcpowers     res = k;
21505697Smcpowers   }
21515697Smcpowers 
21525697Smcpowers CLEANUP:
21535697Smcpowers   mp_clear(&d);
21545697Smcpowers   mp_clear(&f);
21555697Smcpowers   mp_clear(&g);
21565697Smcpowers   return res;
21575697Smcpowers }
21585697Smcpowers 
21595697Smcpowers /* Compute T = (P ** -1) mod MP_RADIX.  Also works for 16-bit mp_digits.
21605697Smcpowers ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
21615697Smcpowers ** by Richard Schroeppel (a.k.a. Captain Nemo).
21625697Smcpowers */
s_mp_invmod_radix(mp_digit P)21635697Smcpowers mp_digit  s_mp_invmod_radix(mp_digit P)
21645697Smcpowers {
21655697Smcpowers   mp_digit T = P;
21665697Smcpowers   T *= 2 - (P * T);
21675697Smcpowers   T *= 2 - (P * T);
21685697Smcpowers   T *= 2 - (P * T);
21695697Smcpowers   T *= 2 - (P * T);
21705697Smcpowers #if !defined(MP_USE_UINT_DIGIT)
21715697Smcpowers   T *= 2 - (P * T);
21725697Smcpowers   T *= 2 - (P * T);
21735697Smcpowers #endif
21745697Smcpowers   return T;
21755697Smcpowers }
21765697Smcpowers 
21775697Smcpowers /* Given c, k, and prime p, where a*c == 2**k (mod p),
21785697Smcpowers ** Compute x = (a ** -1) mod p.  This is similar to Montgomery reduction.
21795697Smcpowers ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
21805697Smcpowers ** by Richard Schroeppel (a.k.a. Captain Nemo).
21815697Smcpowers */
s_mp_fixup_reciprocal(const mp_int * c,const mp_int * p,int k,mp_int * x)21825697Smcpowers mp_err  s_mp_fixup_reciprocal(const mp_int *c, const mp_int *p, int k, mp_int *x)
21835697Smcpowers {
21845697Smcpowers   int      k_orig = k;
21855697Smcpowers   mp_digit r;
21865697Smcpowers   mp_size  ix;
21875697Smcpowers   mp_err   res;
21885697Smcpowers 
21895697Smcpowers   if (mp_cmp_z(c) < 0) {		/* c < 0 */
21905697Smcpowers     MP_CHECKOK( mp_add(c, p, x) );	/* x = c + p */
21915697Smcpowers   } else {
21925697Smcpowers     MP_CHECKOK( mp_copy(c, x) );	/* x = c */
21935697Smcpowers   }
21945697Smcpowers 
21955697Smcpowers   /* make sure x is large enough */
21965697Smcpowers   ix = MP_HOWMANY(k, MP_DIGIT_BIT) + MP_USED(p) + 1;
21975697Smcpowers   ix = MP_MAX(ix, MP_USED(x));
21985697Smcpowers   MP_CHECKOK( s_mp_pad(x, ix) );
21995697Smcpowers 
22005697Smcpowers   r = 0 - s_mp_invmod_radix(MP_DIGIT(p,0));
22015697Smcpowers 
22025697Smcpowers   for (ix = 0; k > 0; ix++) {
22035697Smcpowers     int      j = MP_MIN(k, MP_DIGIT_BIT);
22045697Smcpowers     mp_digit v = r * MP_DIGIT(x, ix);
22055697Smcpowers     if (j < MP_DIGIT_BIT) {
22065697Smcpowers       v &= ((mp_digit)1 << j) - 1;	/* v = v mod (2 ** j) */
22075697Smcpowers     }
22085697Smcpowers     s_mp_mul_d_add_offset(p, v, x, ix); /* x += p * v * (RADIX ** ix) */
22095697Smcpowers     k -= j;
22105697Smcpowers   }
22115697Smcpowers   s_mp_clamp(x);
22125697Smcpowers   s_mp_div_2d(x, k_orig);
22135697Smcpowers   res = MP_OKAY;
22145697Smcpowers 
22155697Smcpowers CLEANUP:
22165697Smcpowers   return res;
22175697Smcpowers }
22185697Smcpowers 
22195697Smcpowers /* compute mod inverse using Schroeppel's method, only if m is odd */
s_mp_invmod_odd_m(const mp_int * a,const mp_int * m,mp_int * c)22205697Smcpowers mp_err s_mp_invmod_odd_m(const mp_int *a, const mp_int *m, mp_int *c)
22215697Smcpowers {
22225697Smcpowers   int k;
22235697Smcpowers   mp_err  res;
22245697Smcpowers   mp_int  x;
22255697Smcpowers 
22265697Smcpowers   ARGCHK(a && m && c, MP_BADARG);
22275697Smcpowers 
22285697Smcpowers   if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
22295697Smcpowers     return MP_RANGE;
22305697Smcpowers   if (mp_iseven(m))
22315697Smcpowers     return MP_UNDEF;
22325697Smcpowers 
22335697Smcpowers   MP_DIGITS(&x) = 0;
22345697Smcpowers 
22355697Smcpowers   if (a == c) {
22365697Smcpowers     if ((res = mp_init_copy(&x, a)) != MP_OKAY)
22375697Smcpowers       return res;
22385697Smcpowers     if (a == m)
22395697Smcpowers       m = &x;
22405697Smcpowers     a = &x;
22415697Smcpowers   } else if (m == c) {
22425697Smcpowers     if ((res = mp_init_copy(&x, m)) != MP_OKAY)
22435697Smcpowers       return res;
22445697Smcpowers     m = &x;
22455697Smcpowers   } else {
22465697Smcpowers     MP_DIGITS(&x) = 0;
22475697Smcpowers   }
22485697Smcpowers 
22495697Smcpowers   MP_CHECKOK( s_mp_almost_inverse(a, m, c) );
22505697Smcpowers   k = res;
22515697Smcpowers   MP_CHECKOK( s_mp_fixup_reciprocal(c, m, k, c) );
22525697Smcpowers CLEANUP:
22535697Smcpowers   mp_clear(&x);
22545697Smcpowers   return res;
22555697Smcpowers }
22565697Smcpowers 
22575697Smcpowers /* Known good algorithm for computing modular inverse.  But slow. */
mp_invmod_xgcd(const mp_int * a,const mp_int * m,mp_int * c)22585697Smcpowers mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c)
22595697Smcpowers {
22605697Smcpowers   mp_int  g, x;
22615697Smcpowers   mp_err  res;
22625697Smcpowers 
22635697Smcpowers   ARGCHK(a && m && c, MP_BADARG);
22645697Smcpowers 
22655697Smcpowers   if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
22665697Smcpowers     return MP_RANGE;
22675697Smcpowers 
22685697Smcpowers   MP_DIGITS(&g) = 0;
22695697Smcpowers   MP_DIGITS(&x) = 0;
22705697Smcpowers   MP_CHECKOK( mp_init(&x, FLAG(a)) );
22715697Smcpowers   MP_CHECKOK( mp_init(&g, FLAG(a)) );
22725697Smcpowers 
22735697Smcpowers   MP_CHECKOK( mp_xgcd(a, m, &g, &x, NULL) );
22745697Smcpowers 
22755697Smcpowers   if (mp_cmp_d(&g, 1) != MP_EQ) {
22765697Smcpowers     res = MP_UNDEF;
22775697Smcpowers     goto CLEANUP;
22785697Smcpowers   }
22795697Smcpowers 
22805697Smcpowers   res = mp_mod(&x, m, c);
22815697Smcpowers   SIGN(c) = SIGN(a);
22825697Smcpowers 
22835697Smcpowers CLEANUP:
22845697Smcpowers   mp_clear(&x);
22855697Smcpowers   mp_clear(&g);
22865697Smcpowers 
22875697Smcpowers   return res;
22885697Smcpowers }
22895697Smcpowers 
22905697Smcpowers /* modular inverse where modulus is 2**k. */
22915697Smcpowers /* c = a**-1 mod 2**k */
s_mp_invmod_2d(const mp_int * a,mp_size k,mp_int * c)22925697Smcpowers mp_err s_mp_invmod_2d(const mp_int *a, mp_size k, mp_int *c)
22935697Smcpowers {
22945697Smcpowers   mp_err res;
22955697Smcpowers   mp_size ix = k + 4;
22965697Smcpowers   mp_int t0, t1, val, tmp, two2k;
22975697Smcpowers 
22985697Smcpowers   static const mp_digit d2 = 2;
22995697Smcpowers   static const mp_int two = { 0, MP_ZPOS, 1, 1, (mp_digit *)&d2 };
23005697Smcpowers 
23015697Smcpowers   if (mp_iseven(a))
23025697Smcpowers     return MP_UNDEF;
23035697Smcpowers   if (k <= MP_DIGIT_BIT) {
23045697Smcpowers     mp_digit i = s_mp_invmod_radix(MP_DIGIT(a,0));
23055697Smcpowers     if (k < MP_DIGIT_BIT)
23065697Smcpowers       i &= ((mp_digit)1 << k) - (mp_digit)1;
23075697Smcpowers     mp_set(c, i);
23085697Smcpowers     return MP_OKAY;
23095697Smcpowers   }
23105697Smcpowers   MP_DIGITS(&t0) = 0;
23115697Smcpowers   MP_DIGITS(&t1) = 0;
23125697Smcpowers   MP_DIGITS(&val) = 0;
23135697Smcpowers   MP_DIGITS(&tmp) = 0;
23145697Smcpowers   MP_DIGITS(&two2k) = 0;
23155697Smcpowers   MP_CHECKOK( mp_init_copy(&val, a) );
23165697Smcpowers   s_mp_mod_2d(&val, k);
23175697Smcpowers   MP_CHECKOK( mp_init_copy(&t0, &val) );
23185697Smcpowers   MP_CHECKOK( mp_init_copy(&t1, &t0)  );
23195697Smcpowers   MP_CHECKOK( mp_init(&tmp, FLAG(a)) );
23205697Smcpowers   MP_CHECKOK( mp_init(&two2k, FLAG(a)) );
23215697Smcpowers   MP_CHECKOK( s_mp_2expt(&two2k, k) );
23225697Smcpowers   do {
23235697Smcpowers     MP_CHECKOK( mp_mul(&val, &t1, &tmp)  );
23245697Smcpowers     MP_CHECKOK( mp_sub(&two, &tmp, &tmp) );
23255697Smcpowers     MP_CHECKOK( mp_mul(&t1, &tmp, &t1)   );
23265697Smcpowers     s_mp_mod_2d(&t1, k);
23275697Smcpowers     while (MP_SIGN(&t1) != MP_ZPOS) {
23285697Smcpowers       MP_CHECKOK( mp_add(&t1, &two2k, &t1) );
23295697Smcpowers     }
23305697Smcpowers     if (mp_cmp(&t1, &t0) == MP_EQ)
23315697Smcpowers       break;
23325697Smcpowers     MP_CHECKOK( mp_copy(&t1, &t0) );
23335697Smcpowers   } while (--ix > 0);
23345697Smcpowers   if (!ix) {
23355697Smcpowers     res = MP_UNDEF;
23365697Smcpowers   } else {
23375697Smcpowers     mp_exch(c, &t1);
23385697Smcpowers   }
23395697Smcpowers 
23405697Smcpowers CLEANUP:
23415697Smcpowers   mp_clear(&t0);
23425697Smcpowers   mp_clear(&t1);
23435697Smcpowers   mp_clear(&val);
23445697Smcpowers   mp_clear(&tmp);
23455697Smcpowers   mp_clear(&two2k);
23465697Smcpowers   return res;
23475697Smcpowers }
23485697Smcpowers 
s_mp_invmod_even_m(const mp_int * a,const mp_int * m,mp_int * c)23495697Smcpowers mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c)
23505697Smcpowers {
23515697Smcpowers   mp_err res;
23525697Smcpowers   mp_size k;
23535697Smcpowers   mp_int oddFactor, evenFactor;	/* factors of the modulus */
23545697Smcpowers   mp_int oddPart, evenPart;	/* parts to combine via CRT. */
23555697Smcpowers   mp_int C2, tmp1, tmp2;
23565697Smcpowers 
23575697Smcpowers   /*static const mp_digit d1 = 1; */
23585697Smcpowers   /*static const mp_int one = { MP_ZPOS, 1, 1, (mp_digit *)&d1 }; */
23595697Smcpowers 
23605697Smcpowers   if ((res = s_mp_ispow2(m)) >= 0) {
23615697Smcpowers     k = res;
23625697Smcpowers     return s_mp_invmod_2d(a, k, c);
23635697Smcpowers   }
23645697Smcpowers   MP_DIGITS(&oddFactor) = 0;
23655697Smcpowers   MP_DIGITS(&evenFactor) = 0;
23665697Smcpowers   MP_DIGITS(&oddPart) = 0;
23675697Smcpowers   MP_DIGITS(&evenPart) = 0;
23685697Smcpowers   MP_DIGITS(&C2)     = 0;
23695697Smcpowers   MP_DIGITS(&tmp1)   = 0;
23705697Smcpowers   MP_DIGITS(&tmp2)   = 0;
23715697Smcpowers 
23725697Smcpowers   MP_CHECKOK( mp_init_copy(&oddFactor, m) );    /* oddFactor = m */
23735697Smcpowers   MP_CHECKOK( mp_init(&evenFactor, FLAG(m)) );
23745697Smcpowers   MP_CHECKOK( mp_init(&oddPart, FLAG(m)) );
23755697Smcpowers   MP_CHECKOK( mp_init(&evenPart, FLAG(m)) );
23765697Smcpowers   MP_CHECKOK( mp_init(&C2, FLAG(m))     );
23775697Smcpowers   MP_CHECKOK( mp_init(&tmp1, FLAG(m))   );
23785697Smcpowers   MP_CHECKOK( mp_init(&tmp2, FLAG(m))   );
23795697Smcpowers 
23805697Smcpowers   k = mp_trailing_zeros(m);
23815697Smcpowers   s_mp_div_2d(&oddFactor, k);
23825697Smcpowers   MP_CHECKOK( s_mp_2expt(&evenFactor, k) );
23835697Smcpowers 
23845697Smcpowers   /* compute a**-1 mod oddFactor. */
23855697Smcpowers   MP_CHECKOK( s_mp_invmod_odd_m(a, &oddFactor, &oddPart) );
23865697Smcpowers   /* compute a**-1 mod evenFactor, where evenFactor == 2**k. */
23875697Smcpowers   MP_CHECKOK( s_mp_invmod_2d(   a,       k,    &evenPart) );
23885697Smcpowers 
23895697Smcpowers   /* Use Chinese Remainer theorem to compute a**-1 mod m. */
23905697Smcpowers   /* let m1 = oddFactor,  v1 = oddPart,
23915697Smcpowers    * let m2 = evenFactor, v2 = evenPart.
23925697Smcpowers    */
23935697Smcpowers 
23945697Smcpowers   /* Compute C2 = m1**-1 mod m2. */
23955697Smcpowers   MP_CHECKOK( s_mp_invmod_2d(&oddFactor, k,    &C2) );
23965697Smcpowers 
23975697Smcpowers   /* compute u = (v2 - v1)*C2 mod m2 */
23985697Smcpowers   MP_CHECKOK( mp_sub(&evenPart, &oddPart,   &tmp1) );
23995697Smcpowers   MP_CHECKOK( mp_mul(&tmp1,     &C2,        &tmp2) );
24005697Smcpowers   s_mp_mod_2d(&tmp2, k);
24015697Smcpowers   while (MP_SIGN(&tmp2) != MP_ZPOS) {
24025697Smcpowers     MP_CHECKOK( mp_add(&tmp2, &evenFactor, &tmp2) );
24035697Smcpowers   }
24045697Smcpowers 
24055697Smcpowers   /* compute answer = v1 + u*m1 */
24065697Smcpowers   MP_CHECKOK( mp_mul(&tmp2,     &oddFactor, c) );
24075697Smcpowers   MP_CHECKOK( mp_add(&oddPart,  c,          c) );
24085697Smcpowers   /* not sure this is necessary, but it's low cost if not. */
24095697Smcpowers   MP_CHECKOK( mp_mod(c,         m,          c) );
24105697Smcpowers 
24115697Smcpowers CLEANUP:
24125697Smcpowers   mp_clear(&oddFactor);
24135697Smcpowers   mp_clear(&evenFactor);
24145697Smcpowers   mp_clear(&oddPart);
24155697Smcpowers   mp_clear(&evenPart);
24165697Smcpowers   mp_clear(&C2);
24175697Smcpowers   mp_clear(&tmp1);
24185697Smcpowers   mp_clear(&tmp2);
24195697Smcpowers   return res;
24205697Smcpowers }
24215697Smcpowers 
24225697Smcpowers 
24235697Smcpowers /* {{{ mp_invmod(a, m, c) */
24245697Smcpowers 
24255697Smcpowers /*
24265697Smcpowers   mp_invmod(a, m, c)
24275697Smcpowers 
24285697Smcpowers   Compute c = a^-1 (mod m), if there is an inverse for a (mod m).
24295697Smcpowers   This is equivalent to the question of whether (a, m) = 1.  If not,
24305697Smcpowers   MP_UNDEF is returned, and there is no inverse.
24315697Smcpowers  */
24325697Smcpowers 
mp_invmod(const mp_int * a,const mp_int * m,mp_int * c)24335697Smcpowers mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
24345697Smcpowers {
24355697Smcpowers 
24365697Smcpowers   ARGCHK(a && m && c, MP_BADARG);
24375697Smcpowers 
24385697Smcpowers   if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
24395697Smcpowers     return MP_RANGE;
24405697Smcpowers 
24415697Smcpowers   if (mp_isodd(m)) {
24425697Smcpowers     return s_mp_invmod_odd_m(a, m, c);
24435697Smcpowers   }
24445697Smcpowers   if (mp_iseven(a))
24455697Smcpowers     return MP_UNDEF;	/* not invertable */
24465697Smcpowers 
24475697Smcpowers   return s_mp_invmod_even_m(a, m, c);
24485697Smcpowers 
24495697Smcpowers } /* end mp_invmod() */
24505697Smcpowers 
24515697Smcpowers /* }}} */
24525697Smcpowers #endif /* if MP_NUMTH */
24535697Smcpowers 
24545697Smcpowers /* }}} */
24555697Smcpowers 
24565697Smcpowers /*------------------------------------------------------------------------*/
24575697Smcpowers /* {{{ mp_print(mp, ofp) */
24585697Smcpowers 
24595697Smcpowers #if MP_IOFUNC
24605697Smcpowers /*
24615697Smcpowers   mp_print(mp, ofp)
24625697Smcpowers 
24635697Smcpowers   Print a textual representation of the given mp_int on the output
24645697Smcpowers   stream 'ofp'.  Output is generated using the internal radix.
24655697Smcpowers  */
24665697Smcpowers 
mp_print(mp_int * mp,FILE * ofp)24675697Smcpowers void   mp_print(mp_int *mp, FILE *ofp)
24685697Smcpowers {
24695697Smcpowers   int   ix;
24705697Smcpowers 
24715697Smcpowers   if(mp == NULL || ofp == NULL)
24725697Smcpowers     return;
24735697Smcpowers 
24745697Smcpowers   fputc((SIGN(mp) == NEG) ? '-' : '+', ofp);
24755697Smcpowers 
24765697Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
24775697Smcpowers     fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix));
24785697Smcpowers   }
24795697Smcpowers 
24805697Smcpowers } /* end mp_print() */
24815697Smcpowers 
24825697Smcpowers #endif /* if MP_IOFUNC */
24835697Smcpowers 
24845697Smcpowers /* }}} */
24855697Smcpowers 
24865697Smcpowers /*------------------------------------------------------------------------*/
24875697Smcpowers /* {{{ More I/O Functions */
24885697Smcpowers 
24895697Smcpowers /* {{{ mp_read_raw(mp, str, len) */
24905697Smcpowers 
24915697Smcpowers /*
24925697Smcpowers    mp_read_raw(mp, str, len)
24935697Smcpowers 
24945697Smcpowers    Read in a raw value (base 256) into the given mp_int
24955697Smcpowers  */
24965697Smcpowers 
mp_read_raw(mp_int * mp,char * str,int len)24975697Smcpowers mp_err  mp_read_raw(mp_int *mp, char *str, int len)
24985697Smcpowers {
24995697Smcpowers   int            ix;
25005697Smcpowers   mp_err         res;
25015697Smcpowers   unsigned char *ustr = (unsigned char *)str;
25025697Smcpowers 
25035697Smcpowers   ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
25045697Smcpowers 
25055697Smcpowers   mp_zero(mp);
25065697Smcpowers 
25075697Smcpowers   /* Get sign from first byte */
25085697Smcpowers   if(ustr[0])
25095697Smcpowers     SIGN(mp) = NEG;
25105697Smcpowers   else
25115697Smcpowers     SIGN(mp) = ZPOS;
25125697Smcpowers 
25135697Smcpowers   /* Read the rest of the digits */
25145697Smcpowers   for(ix = 1; ix < len; ix++) {
25155697Smcpowers     if((res = mp_mul_d(mp, 256, mp)) != MP_OKAY)
25165697Smcpowers       return res;
25175697Smcpowers     if((res = mp_add_d(mp, ustr[ix], mp)) != MP_OKAY)
25185697Smcpowers       return res;
25195697Smcpowers   }
25205697Smcpowers 
25215697Smcpowers   return MP_OKAY;
25225697Smcpowers 
25235697Smcpowers } /* end mp_read_raw() */
25245697Smcpowers 
25255697Smcpowers /* }}} */
25265697Smcpowers 
25275697Smcpowers /* {{{ mp_raw_size(mp) */
25285697Smcpowers 
mp_raw_size(mp_int * mp)25295697Smcpowers int    mp_raw_size(mp_int *mp)
25305697Smcpowers {
25315697Smcpowers   ARGCHK(mp != NULL, 0);
25325697Smcpowers 
25335697Smcpowers   return (USED(mp) * sizeof(mp_digit)) + 1;
25345697Smcpowers 
25355697Smcpowers } /* end mp_raw_size() */
25365697Smcpowers 
25375697Smcpowers /* }}} */
25385697Smcpowers 
25395697Smcpowers /* {{{ mp_toraw(mp, str) */
25405697Smcpowers 
mp_toraw(mp_int * mp,char * str)25415697Smcpowers mp_err mp_toraw(mp_int *mp, char *str)
25425697Smcpowers {
25435697Smcpowers   int  ix, jx, pos = 1;
25445697Smcpowers 
25455697Smcpowers   ARGCHK(mp != NULL && str != NULL, MP_BADARG);
25465697Smcpowers 
25475697Smcpowers   str[0] = (char)SIGN(mp);
25485697Smcpowers 
25495697Smcpowers   /* Iterate over each digit... */
25505697Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
25515697Smcpowers     mp_digit  d = DIGIT(mp, ix);
25525697Smcpowers 
25535697Smcpowers     /* Unpack digit bytes, high order first */
25545697Smcpowers     for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
25555697Smcpowers       str[pos++] = (char)(d >> (jx * CHAR_BIT));
25565697Smcpowers     }
25575697Smcpowers   }
25585697Smcpowers 
25595697Smcpowers   return MP_OKAY;
25605697Smcpowers 
25615697Smcpowers } /* end mp_toraw() */
25625697Smcpowers 
25635697Smcpowers /* }}} */
25645697Smcpowers 
25655697Smcpowers /* {{{ mp_read_radix(mp, str, radix) */
25665697Smcpowers 
25675697Smcpowers /*
25685697Smcpowers   mp_read_radix(mp, str, radix)
25695697Smcpowers 
25705697Smcpowers   Read an integer from the given string, and set mp to the resulting
25715697Smcpowers   value.  The input is presumed to be in base 10.  Leading non-digit
25725697Smcpowers   characters are ignored, and the function reads until a non-digit
25735697Smcpowers   character or the end of the string.
25745697Smcpowers  */
25755697Smcpowers 
mp_read_radix(mp_int * mp,const char * str,int radix)25765697Smcpowers mp_err  mp_read_radix(mp_int *mp, const char *str, int radix)
25775697Smcpowers {
25785697Smcpowers   int     ix = 0, val = 0;
25795697Smcpowers   mp_err  res;
25805697Smcpowers   mp_sign sig = ZPOS;
25815697Smcpowers 
25825697Smcpowers   ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX,
25835697Smcpowers 	 MP_BADARG);
25845697Smcpowers 
25855697Smcpowers   mp_zero(mp);
25865697Smcpowers 
25875697Smcpowers   /* Skip leading non-digit characters until a digit or '-' or '+' */
25885697Smcpowers   while(str[ix] &&
25895697Smcpowers 	(s_mp_tovalue(str[ix], radix) < 0) &&
25905697Smcpowers 	str[ix] != '-' &&
25915697Smcpowers 	str[ix] != '+') {
25925697Smcpowers     ++ix;
25935697Smcpowers   }
25945697Smcpowers 
25955697Smcpowers   if(str[ix] == '-') {
25965697Smcpowers     sig = NEG;
25975697Smcpowers     ++ix;
25985697Smcpowers   } else if(str[ix] == '+') {
25995697Smcpowers     sig = ZPOS; /* this is the default anyway... */
26005697Smcpowers     ++ix;
26015697Smcpowers   }
26025697Smcpowers 
26035697Smcpowers   while((val = s_mp_tovalue(str[ix], radix)) >= 0) {
26045697Smcpowers     if((res = s_mp_mul_d(mp, radix)) != MP_OKAY)
26055697Smcpowers       return res;
26065697Smcpowers     if((res = s_mp_add_d(mp, val)) != MP_OKAY)
26075697Smcpowers       return res;
26085697Smcpowers     ++ix;
26095697Smcpowers   }
26105697Smcpowers 
26115697Smcpowers   if(s_mp_cmp_d(mp, 0) == MP_EQ)
26125697Smcpowers     SIGN(mp) = ZPOS;
26135697Smcpowers   else
26145697Smcpowers     SIGN(mp) = sig;
26155697Smcpowers 
26165697Smcpowers   return MP_OKAY;
26175697Smcpowers 
26185697Smcpowers } /* end mp_read_radix() */
26195697Smcpowers 
mp_read_variable_radix(mp_int * a,const char * str,int default_radix)26205697Smcpowers mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix)
26215697Smcpowers {
26225697Smcpowers   int     radix = default_radix;
26235697Smcpowers   int     cx;
26245697Smcpowers   mp_sign sig   = ZPOS;
26255697Smcpowers   mp_err  res;
26265697Smcpowers 
26275697Smcpowers   /* Skip leading non-digit characters until a digit or '-' or '+' */
26285697Smcpowers   while ((cx = *str) != 0 &&
26295697Smcpowers 	(s_mp_tovalue(cx, radix) < 0) &&
26305697Smcpowers 	cx != '-' &&
26315697Smcpowers 	cx != '+') {
26325697Smcpowers     ++str;
26335697Smcpowers   }
26345697Smcpowers 
26355697Smcpowers   if (cx == '-') {
26365697Smcpowers     sig = NEG;
26375697Smcpowers     ++str;
26385697Smcpowers   } else if (cx == '+') {
26395697Smcpowers     sig = ZPOS; /* this is the default anyway... */
26405697Smcpowers     ++str;
26415697Smcpowers   }
26425697Smcpowers 
26435697Smcpowers   if (str[0] == '0') {
26445697Smcpowers     if ((str[1] | 0x20) == 'x') {
26455697Smcpowers       radix = 16;
26465697Smcpowers       str += 2;
26475697Smcpowers     } else {
26485697Smcpowers       radix = 8;
26495697Smcpowers       str++;
26505697Smcpowers     }
26515697Smcpowers   }
26525697Smcpowers   res = mp_read_radix(a, str, radix);
26535697Smcpowers   if (res == MP_OKAY) {
26545697Smcpowers     MP_SIGN(a) = (s_mp_cmp_d(a, 0) == MP_EQ) ? ZPOS : sig;
26555697Smcpowers   }
26565697Smcpowers   return res;
26575697Smcpowers }
26585697Smcpowers 
26595697Smcpowers /* }}} */
26605697Smcpowers 
26615697Smcpowers /* {{{ mp_radix_size(mp, radix) */
26625697Smcpowers 
mp_radix_size(mp_int * mp,int radix)26635697Smcpowers int    mp_radix_size(mp_int *mp, int radix)
26645697Smcpowers {
26655697Smcpowers   int  bits;
26665697Smcpowers 
26675697Smcpowers   if(!mp || radix < 2 || radix > MAX_RADIX)
26685697Smcpowers     return 0;
26695697Smcpowers 
26705697Smcpowers   bits = USED(mp) * DIGIT_BIT - 1;
26715697Smcpowers 
26725697Smcpowers   return s_mp_outlen(bits, radix);
26735697Smcpowers 
26745697Smcpowers } /* end mp_radix_size() */
26755697Smcpowers 
26765697Smcpowers /* }}} */
26775697Smcpowers 
26785697Smcpowers /* {{{ mp_toradix(mp, str, radix) */
26795697Smcpowers 
mp_toradix(mp_int * mp,char * str,int radix)26805697Smcpowers mp_err mp_toradix(mp_int *mp, char *str, int radix)
26815697Smcpowers {
26825697Smcpowers   int  ix, pos = 0;
26835697Smcpowers 
26845697Smcpowers   ARGCHK(mp != NULL && str != NULL, MP_BADARG);
26855697Smcpowers   ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE);
26865697Smcpowers 
26875697Smcpowers   if(mp_cmp_z(mp) == MP_EQ) {
26885697Smcpowers     str[0] = '0';
26895697Smcpowers     str[1] = '\0';
26905697Smcpowers   } else {
26915697Smcpowers     mp_err   res;
26925697Smcpowers     mp_int   tmp;
26935697Smcpowers     mp_sign  sgn;
26945697Smcpowers     mp_digit rem, rdx = (mp_digit)radix;
26955697Smcpowers     char     ch;
26965697Smcpowers 
26975697Smcpowers     if((res = mp_init_copy(&tmp, mp)) != MP_OKAY)
26985697Smcpowers       return res;
26995697Smcpowers 
27005697Smcpowers     /* Save sign for later, and take absolute value */
27015697Smcpowers     sgn = SIGN(&tmp); SIGN(&tmp) = ZPOS;
27025697Smcpowers 
27035697Smcpowers     /* Generate output digits in reverse order      */
27045697Smcpowers     while(mp_cmp_z(&tmp) != 0) {
27055697Smcpowers       if((res = mp_div_d(&tmp, rdx, &tmp, &rem)) != MP_OKAY) {
27065697Smcpowers 	mp_clear(&tmp);
27075697Smcpowers 	return res;
27085697Smcpowers       }
27095697Smcpowers 
27105697Smcpowers       /* Generate digits, use capital letters */
27115697Smcpowers       ch = s_mp_todigit(rem, radix, 0);
27125697Smcpowers 
27135697Smcpowers       str[pos++] = ch;
27145697Smcpowers     }
27155697Smcpowers 
27165697Smcpowers     /* Add - sign if original value was negative */
27175697Smcpowers     if(sgn == NEG)
27185697Smcpowers       str[pos++] = '-';
27195697Smcpowers 
27205697Smcpowers     /* Add trailing NUL to end the string        */
27215697Smcpowers     str[pos--] = '\0';
27225697Smcpowers 
27235697Smcpowers     /* Reverse the digits and sign indicator     */
27245697Smcpowers     ix = 0;
27255697Smcpowers     while(ix < pos) {
27265697Smcpowers       char tmp = str[ix];
27275697Smcpowers 
27285697Smcpowers       str[ix] = str[pos];
27295697Smcpowers       str[pos] = tmp;
27305697Smcpowers       ++ix;
27315697Smcpowers       --pos;
27325697Smcpowers     }
27335697Smcpowers 
27345697Smcpowers     mp_clear(&tmp);
27355697Smcpowers   }
27365697Smcpowers 
27375697Smcpowers   return MP_OKAY;
27385697Smcpowers 
27395697Smcpowers } /* end mp_toradix() */
27405697Smcpowers 
27415697Smcpowers /* }}} */
27425697Smcpowers 
27435697Smcpowers /* {{{ mp_tovalue(ch, r) */
27445697Smcpowers 
mp_tovalue(char ch,int r)27455697Smcpowers int    mp_tovalue(char ch, int r)
27465697Smcpowers {
27475697Smcpowers   return s_mp_tovalue(ch, r);
27485697Smcpowers 
27495697Smcpowers } /* end mp_tovalue() */
27505697Smcpowers 
27515697Smcpowers /* }}} */
27525697Smcpowers 
27535697Smcpowers /* }}} */
27545697Smcpowers 
27555697Smcpowers /* {{{ mp_strerror(ec) */
27565697Smcpowers 
27575697Smcpowers /*
27585697Smcpowers   mp_strerror(ec)
27595697Smcpowers 
27605697Smcpowers   Return a string describing the meaning of error code 'ec'.  The
27615697Smcpowers   string returned is allocated in static memory, so the caller should
27625697Smcpowers   not attempt to modify or free the memory associated with this
27635697Smcpowers   string.
27645697Smcpowers  */
mp_strerror(mp_err ec)27655697Smcpowers const char  *mp_strerror(mp_err ec)
27665697Smcpowers {
27675697Smcpowers   int   aec = (ec < 0) ? -ec : ec;
27685697Smcpowers 
27695697Smcpowers   /* Code values are negative, so the senses of these comparisons
27705697Smcpowers      are accurate */
27715697Smcpowers   if(ec < MP_LAST_CODE || ec > MP_OKAY) {
27725697Smcpowers     return mp_err_string[0];  /* unknown error code */
27735697Smcpowers   } else {
27745697Smcpowers     return mp_err_string[aec + 1];
27755697Smcpowers   }
27765697Smcpowers 
27775697Smcpowers } /* end mp_strerror() */
27785697Smcpowers 
27795697Smcpowers /* }}} */
27805697Smcpowers 
27815697Smcpowers /*========================================================================*/
27825697Smcpowers /*------------------------------------------------------------------------*/
27835697Smcpowers /* Static function definitions (internal use only)                        */
27845697Smcpowers 
27855697Smcpowers /* {{{ Memory management */
27865697Smcpowers 
27875697Smcpowers /* {{{ s_mp_grow(mp, min) */
27885697Smcpowers 
27895697Smcpowers /* Make sure there are at least 'min' digits allocated to mp              */
s_mp_grow(mp_int * mp,mp_size min)27905697Smcpowers mp_err   s_mp_grow(mp_int *mp, mp_size min)
27915697Smcpowers {
27925697Smcpowers   if(min > ALLOC(mp)) {
27935697Smcpowers     mp_digit   *tmp;
27945697Smcpowers 
27955697Smcpowers     /* Set min to next nearest default precision block size */
27965697Smcpowers     min = MP_ROUNDUP(min, s_mp_defprec);
27975697Smcpowers 
27985697Smcpowers     if((tmp = s_mp_alloc(min, sizeof(mp_digit), FLAG(mp))) == NULL)
27995697Smcpowers       return MP_MEM;
28005697Smcpowers 
28015697Smcpowers     s_mp_copy(DIGITS(mp), tmp, USED(mp));
28025697Smcpowers 
28035697Smcpowers #if MP_CRYPTO
28045697Smcpowers     s_mp_setz(DIGITS(mp), ALLOC(mp));
28055697Smcpowers #endif
28065697Smcpowers     s_mp_free(DIGITS(mp), ALLOC(mp));
28075697Smcpowers     DIGITS(mp) = tmp;
28085697Smcpowers     ALLOC(mp) = min;
28095697Smcpowers   }
28105697Smcpowers 
28115697Smcpowers   return MP_OKAY;
28125697Smcpowers 
28135697Smcpowers } /* end s_mp_grow() */
28145697Smcpowers 
28155697Smcpowers /* }}} */
28165697Smcpowers 
28175697Smcpowers /* {{{ s_mp_pad(mp, min) */
28185697Smcpowers 
28195697Smcpowers /* Make sure the used size of mp is at least 'min', growing if needed     */
s_mp_pad(mp_int * mp,mp_size min)28205697Smcpowers mp_err   s_mp_pad(mp_int *mp, mp_size min)
28215697Smcpowers {
28225697Smcpowers   if(min > USED(mp)) {
28235697Smcpowers     mp_err  res;
28245697Smcpowers 
28255697Smcpowers     /* Make sure there is room to increase precision  */
28265697Smcpowers     if (min > ALLOC(mp)) {
28275697Smcpowers       if ((res = s_mp_grow(mp, min)) != MP_OKAY)
28285697Smcpowers 	return res;
28295697Smcpowers     } else {
28305697Smcpowers       s_mp_setz(DIGITS(mp) + USED(mp), min - USED(mp));
28315697Smcpowers     }
28325697Smcpowers 
28335697Smcpowers     /* Increase precision; should already be 0-filled */
28345697Smcpowers     USED(mp) = min;
28355697Smcpowers   }
28365697Smcpowers 
28375697Smcpowers   return MP_OKAY;
28385697Smcpowers 
28395697Smcpowers } /* end s_mp_pad() */
28405697Smcpowers 
28415697Smcpowers /* }}} */
28425697Smcpowers 
28435697Smcpowers /* {{{ s_mp_setz(dp, count) */
28445697Smcpowers 
28455697Smcpowers #if MP_MACRO == 0
28465697Smcpowers /* Set 'count' digits pointed to by dp to be zeroes                       */
s_mp_setz(mp_digit * dp,mp_size count)28475697Smcpowers void s_mp_setz(mp_digit *dp, mp_size count)
28485697Smcpowers {
28495697Smcpowers #if MP_MEMSET == 0
28505697Smcpowers   int  ix;
28515697Smcpowers 
28525697Smcpowers   for(ix = 0; ix < count; ix++)
28535697Smcpowers     dp[ix] = 0;
28545697Smcpowers #else
28555697Smcpowers   memset(dp, 0, count * sizeof(mp_digit));
28565697Smcpowers #endif
28575697Smcpowers 
28585697Smcpowers } /* end s_mp_setz() */
28595697Smcpowers #endif
28605697Smcpowers 
28615697Smcpowers /* }}} */
28625697Smcpowers 
28635697Smcpowers /* {{{ s_mp_copy(sp, dp, count) */
28645697Smcpowers 
28655697Smcpowers #if MP_MACRO == 0
28665697Smcpowers /* Copy 'count' digits from sp to dp                                      */
s_mp_copy(const mp_digit * sp,mp_digit * dp,mp_size count)28675697Smcpowers void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count)
28685697Smcpowers {
28695697Smcpowers #if MP_MEMCPY == 0
28705697Smcpowers   int  ix;
28715697Smcpowers 
28725697Smcpowers   for(ix = 0; ix < count; ix++)
28735697Smcpowers     dp[ix] = sp[ix];
28745697Smcpowers #else
28755697Smcpowers   memcpy(dp, sp, count * sizeof(mp_digit));
28765697Smcpowers #endif
28775697Smcpowers 
28785697Smcpowers } /* end s_mp_copy() */
28795697Smcpowers #endif
28805697Smcpowers 
28815697Smcpowers /* }}} */
28825697Smcpowers 
28835697Smcpowers /* {{{ s_mp_alloc(nb, ni, kmflag) */
28845697Smcpowers 
28855697Smcpowers #if MP_MACRO == 0
28865697Smcpowers /* Allocate ni records of nb bytes each, and return a pointer to that     */
s_mp_alloc(size_t nb,size_t ni,int kmflag)28875697Smcpowers void    *s_mp_alloc(size_t nb, size_t ni, int kmflag)
28885697Smcpowers {
28895697Smcpowers   ++mp_allocs;
28905697Smcpowers #ifdef _KERNEL
2891*13066SDina.Nimeh@Sun.COM   return kmem_zalloc(nb * ni, kmflag);
28925697Smcpowers #else
28935697Smcpowers   return calloc(nb, ni);
28945697Smcpowers #endif
28955697Smcpowers 
28965697Smcpowers } /* end s_mp_alloc() */
28975697Smcpowers #endif
28985697Smcpowers 
28995697Smcpowers /* }}} */
29005697Smcpowers 
29015697Smcpowers /* {{{ s_mp_free(ptr) */
29025697Smcpowers 
29035697Smcpowers #if MP_MACRO == 0
29045697Smcpowers /* Free the memory pointed to by ptr                                      */
s_mp_free(void * ptr,mp_size alloc)29055697Smcpowers void     s_mp_free(void *ptr, mp_size alloc)
29065697Smcpowers {
29075697Smcpowers   if(ptr) {
29085697Smcpowers     ++mp_frees;
29095697Smcpowers #ifdef _KERNEL
29105697Smcpowers     kmem_free(ptr, alloc * sizeof (mp_digit));
29115697Smcpowers #else
29125697Smcpowers     free(ptr);
29135697Smcpowers #endif
29145697Smcpowers   }
29155697Smcpowers } /* end s_mp_free() */
29165697Smcpowers #endif
29175697Smcpowers 
29185697Smcpowers /* }}} */
29195697Smcpowers 
29205697Smcpowers /* {{{ s_mp_clamp(mp) */
29215697Smcpowers 
29225697Smcpowers #if MP_MACRO == 0
29235697Smcpowers /* Remove leading zeroes from the given value                             */
s_mp_clamp(mp_int * mp)29245697Smcpowers void     s_mp_clamp(mp_int *mp)
29255697Smcpowers {
29265697Smcpowers   mp_size used = MP_USED(mp);
29275697Smcpowers   while (used > 1 && DIGIT(mp, used - 1) == 0)
29285697Smcpowers     --used;
29295697Smcpowers   MP_USED(mp) = used;
29305697Smcpowers } /* end s_mp_clamp() */
29315697Smcpowers #endif
29325697Smcpowers 
29335697Smcpowers /* }}} */
29345697Smcpowers 
29355697Smcpowers /* {{{ s_mp_exch(a, b) */
29365697Smcpowers 
29375697Smcpowers /* Exchange the data for a and b; (b, a) = (a, b)                         */
s_mp_exch(mp_int * a,mp_int * b)29385697Smcpowers void     s_mp_exch(mp_int *a, mp_int *b)
29395697Smcpowers {
29405697Smcpowers   mp_int   tmp;
29415697Smcpowers 
29425697Smcpowers   tmp = *a;
29435697Smcpowers   *a = *b;
29445697Smcpowers   *b = tmp;
29455697Smcpowers 
29465697Smcpowers } /* end s_mp_exch() */
29475697Smcpowers 
29485697Smcpowers /* }}} */
29495697Smcpowers 
29505697Smcpowers /* }}} */
29515697Smcpowers 
29525697Smcpowers /* {{{ Arithmetic helpers */
29535697Smcpowers 
29545697Smcpowers /* {{{ s_mp_lshd(mp, p) */
29555697Smcpowers 
29565697Smcpowers /*
29575697Smcpowers    Shift mp leftward by p digits, growing if needed, and zero-filling
29585697Smcpowers    the in-shifted digits at the right end.  This is a convenient
29595697Smcpowers    alternative to multiplication by powers of the radix
29605697Smcpowers    The value of USED(mp) must already have been set to the value for
29615697Smcpowers    the shifted result.
29625697Smcpowers  */
29635697Smcpowers 
s_mp_lshd(mp_int * mp,mp_size p)29645697Smcpowers mp_err   s_mp_lshd(mp_int *mp, mp_size p)
29655697Smcpowers {
29665697Smcpowers   mp_err  res;
29675697Smcpowers   mp_size pos;
29685697Smcpowers   int     ix;
29695697Smcpowers 
29705697Smcpowers   if(p == 0)
29715697Smcpowers     return MP_OKAY;
29725697Smcpowers 
29735697Smcpowers   if (MP_USED(mp) == 1 && MP_DIGIT(mp, 0) == 0)
29745697Smcpowers     return MP_OKAY;
29755697Smcpowers 
29765697Smcpowers   if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)
29775697Smcpowers     return res;
29785697Smcpowers 
29795697Smcpowers   pos = USED(mp) - 1;
29805697Smcpowers 
29815697Smcpowers   /* Shift all the significant figures over as needed */
29825697Smcpowers   for(ix = pos - p; ix >= 0; ix--)
29835697Smcpowers     DIGIT(mp, ix + p) = DIGIT(mp, ix);
29845697Smcpowers 
29855697Smcpowers   /* Fill the bottom digits with zeroes */
29865697Smcpowers   for(ix = 0; ix < p; ix++)
29875697Smcpowers     DIGIT(mp, ix) = 0;
29885697Smcpowers 
29895697Smcpowers   return MP_OKAY;
29905697Smcpowers 
29915697Smcpowers } /* end s_mp_lshd() */
29925697Smcpowers 
29935697Smcpowers /* }}} */
29945697Smcpowers 
29955697Smcpowers /* {{{ s_mp_mul_2d(mp, d) */
29965697Smcpowers 
29975697Smcpowers /*
29985697Smcpowers   Multiply the integer by 2^d, where d is a number of bits.  This
29995697Smcpowers   amounts to a bitwise shift of the value.
30005697Smcpowers  */
s_mp_mul_2d(mp_int * mp,mp_digit d)30015697Smcpowers mp_err   s_mp_mul_2d(mp_int *mp, mp_digit d)
30025697Smcpowers {
30035697Smcpowers   mp_err   res;
30045697Smcpowers   mp_digit dshift, bshift;
30055697Smcpowers   mp_digit mask;
30065697Smcpowers 
30075697Smcpowers   ARGCHK(mp != NULL,  MP_BADARG);
30085697Smcpowers 
30095697Smcpowers   dshift = d / MP_DIGIT_BIT;
30105697Smcpowers   bshift = d % MP_DIGIT_BIT;
30115697Smcpowers   /* bits to be shifted out of the top word */
30125697Smcpowers   mask   = ((mp_digit)~0 << (MP_DIGIT_BIT - bshift));
30135697Smcpowers   mask  &= MP_DIGIT(mp, MP_USED(mp) - 1);
30145697Smcpowers 
30155697Smcpowers   if (MP_OKAY != (res = s_mp_pad(mp, MP_USED(mp) + dshift + (mask != 0) )))
30165697Smcpowers     return res;
30175697Smcpowers 
30185697Smcpowers   if (dshift && MP_OKAY != (res = s_mp_lshd(mp, dshift)))
30195697Smcpowers     return res;
30205697Smcpowers 
30215697Smcpowers   if (bshift) {
30225697Smcpowers     mp_digit *pa = MP_DIGITS(mp);
30235697Smcpowers     mp_digit *alim = pa + MP_USED(mp);
30245697Smcpowers     mp_digit  prev = 0;
30255697Smcpowers 
30265697Smcpowers     for (pa += dshift; pa < alim; ) {
30275697Smcpowers       mp_digit x = *pa;
30285697Smcpowers       *pa++ = (x << bshift) | prev;
30295697Smcpowers       prev = x >> (DIGIT_BIT - bshift);
30305697Smcpowers     }
30315697Smcpowers   }
30325697Smcpowers 
30335697Smcpowers   s_mp_clamp(mp);
30345697Smcpowers   return MP_OKAY;
30355697Smcpowers } /* end s_mp_mul_2d() */
30365697Smcpowers 
30375697Smcpowers /* {{{ s_mp_rshd(mp, p) */
30385697Smcpowers 
30395697Smcpowers /*
30405697Smcpowers    Shift mp rightward by p digits.  Maintains the invariant that
30415697Smcpowers    digits above the precision are all zero.  Digits shifted off the
30425697Smcpowers    end are lost.  Cannot fail.
30435697Smcpowers  */
30445697Smcpowers 
s_mp_rshd(mp_int * mp,mp_size p)30455697Smcpowers void     s_mp_rshd(mp_int *mp, mp_size p)
30465697Smcpowers {
30475697Smcpowers   mp_size  ix;
30485697Smcpowers   mp_digit *src, *dst;
30495697Smcpowers 
30505697Smcpowers   if(p == 0)
30515697Smcpowers     return;
30525697Smcpowers 
30535697Smcpowers   /* Shortcut when all digits are to be shifted off */
30545697Smcpowers   if(p >= USED(mp)) {
30555697Smcpowers     s_mp_setz(DIGITS(mp), ALLOC(mp));
30565697Smcpowers     USED(mp) = 1;
30575697Smcpowers     SIGN(mp) = ZPOS;
30585697Smcpowers     return;
30595697Smcpowers   }
30605697Smcpowers 
30615697Smcpowers   /* Shift all the significant figures over as needed */
30625697Smcpowers   dst = MP_DIGITS(mp);
30635697Smcpowers   src = dst + p;
30645697Smcpowers   for (ix = USED(mp) - p; ix > 0; ix--)
30655697Smcpowers     *dst++ = *src++;
30665697Smcpowers 
30675697Smcpowers   MP_USED(mp) -= p;
30685697Smcpowers   /* Fill the top digits with zeroes */
30695697Smcpowers   while (p-- > 0)
30705697Smcpowers     *dst++ = 0;
30715697Smcpowers 
30725697Smcpowers #if 0
30735697Smcpowers   /* Strip off any leading zeroes    */
30745697Smcpowers   s_mp_clamp(mp);
30755697Smcpowers #endif
30765697Smcpowers 
30775697Smcpowers } /* end s_mp_rshd() */
30785697Smcpowers 
30795697Smcpowers /* }}} */
30805697Smcpowers 
30815697Smcpowers /* {{{ s_mp_div_2(mp) */
30825697Smcpowers 
30835697Smcpowers /* Divide by two -- take advantage of radix properties to do it fast      */
s_mp_div_2(mp_int * mp)30845697Smcpowers void     s_mp_div_2(mp_int *mp)
30855697Smcpowers {
30865697Smcpowers   s_mp_div_2d(mp, 1);
30875697Smcpowers 
30885697Smcpowers } /* end s_mp_div_2() */
30895697Smcpowers 
30905697Smcpowers /* }}} */
30915697Smcpowers 
30925697Smcpowers /* {{{ s_mp_mul_2(mp) */
30935697Smcpowers 
s_mp_mul_2(mp_int * mp)30945697Smcpowers mp_err s_mp_mul_2(mp_int *mp)
30955697Smcpowers {
30965697Smcpowers   mp_digit *pd;
30975697Smcpowers   int      ix, used;
30985697Smcpowers   mp_digit kin = 0;
30995697Smcpowers 
31005697Smcpowers   /* Shift digits leftward by 1 bit */
31015697Smcpowers   used = MP_USED(mp);
31025697Smcpowers   pd = MP_DIGITS(mp);
31035697Smcpowers   for (ix = 0; ix < used; ix++) {
31045697Smcpowers     mp_digit d = *pd;
31055697Smcpowers     *pd++ = (d << 1) | kin;
31065697Smcpowers     kin = (d >> (DIGIT_BIT - 1));
31075697Smcpowers   }
31085697Smcpowers 
31095697Smcpowers   /* Deal with rollover from last digit */
31105697Smcpowers   if (kin) {
31115697Smcpowers     if (ix >= ALLOC(mp)) {
31125697Smcpowers       mp_err res;
31135697Smcpowers       if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)
31145697Smcpowers 	return res;
31155697Smcpowers     }
31165697Smcpowers 
31175697Smcpowers     DIGIT(mp, ix) = kin;
31185697Smcpowers     USED(mp) += 1;
31195697Smcpowers   }
31205697Smcpowers 
31215697Smcpowers   return MP_OKAY;
31225697Smcpowers 
31235697Smcpowers } /* end s_mp_mul_2() */
31245697Smcpowers 
31255697Smcpowers /* }}} */
31265697Smcpowers 
31275697Smcpowers /* {{{ s_mp_mod_2d(mp, d) */
31285697Smcpowers 
31295697Smcpowers /*
31305697Smcpowers   Remainder the integer by 2^d, where d is a number of bits.  This
31315697Smcpowers   amounts to a bitwise AND of the value, and does not require the full
31325697Smcpowers   division code
31335697Smcpowers  */
s_mp_mod_2d(mp_int * mp,mp_digit d)31345697Smcpowers void     s_mp_mod_2d(mp_int *mp, mp_digit d)
31355697Smcpowers {
31365697Smcpowers   mp_size  ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);
31375697Smcpowers   mp_size  ix;
31385697Smcpowers   mp_digit dmask;
31395697Smcpowers 
31405697Smcpowers   if(ndig >= USED(mp))
31415697Smcpowers     return;
31425697Smcpowers 
31435697Smcpowers   /* Flush all the bits above 2^d in its digit */
31445697Smcpowers   dmask = ((mp_digit)1 << nbit) - 1;
31455697Smcpowers   DIGIT(mp, ndig) &= dmask;
31465697Smcpowers 
31475697Smcpowers   /* Flush all digits above the one with 2^d in it */
31485697Smcpowers   for(ix = ndig + 1; ix < USED(mp); ix++)
31495697Smcpowers     DIGIT(mp, ix) = 0;
31505697Smcpowers 
31515697Smcpowers   s_mp_clamp(mp);
31525697Smcpowers 
31535697Smcpowers } /* end s_mp_mod_2d() */
31545697Smcpowers 
31555697Smcpowers /* }}} */
31565697Smcpowers 
31575697Smcpowers /* {{{ s_mp_div_2d(mp, d) */
31585697Smcpowers 
31595697Smcpowers /*
31605697Smcpowers   Divide the integer by 2^d, where d is a number of bits.  This
31615697Smcpowers   amounts to a bitwise shift of the value, and does not require the
31625697Smcpowers   full division code (used in Barrett reduction, see below)
31635697Smcpowers  */
s_mp_div_2d(mp_int * mp,mp_digit d)31645697Smcpowers void     s_mp_div_2d(mp_int *mp, mp_digit d)
31655697Smcpowers {
31665697Smcpowers   int       ix;
31675697Smcpowers   mp_digit  save, next, mask;
31685697Smcpowers 
31695697Smcpowers   s_mp_rshd(mp, d / DIGIT_BIT);
31705697Smcpowers   d %= DIGIT_BIT;
31715697Smcpowers   if (d) {
31725697Smcpowers     mask = ((mp_digit)1 << d) - 1;
31735697Smcpowers     save = 0;
31745697Smcpowers     for(ix = USED(mp) - 1; ix >= 0; ix--) {
31755697Smcpowers       next = DIGIT(mp, ix) & mask;
31765697Smcpowers       DIGIT(mp, ix) = (DIGIT(mp, ix) >> d) | (save << (DIGIT_BIT - d));
31775697Smcpowers       save = next;
31785697Smcpowers     }
31795697Smcpowers   }
31805697Smcpowers   s_mp_clamp(mp);
31815697Smcpowers 
31825697Smcpowers } /* end s_mp_div_2d() */
31835697Smcpowers 
31845697Smcpowers /* }}} */
31855697Smcpowers 
31865697Smcpowers /* {{{ s_mp_norm(a, b, *d) */
31875697Smcpowers 
31885697Smcpowers /*
31895697Smcpowers   s_mp_norm(a, b, *d)
31905697Smcpowers 
31915697Smcpowers   Normalize a and b for division, where b is the divisor.  In order
31925697Smcpowers   that we might make good guesses for quotient digits, we want the
31935697Smcpowers   leading digit of b to be at least half the radix, which we
31945697Smcpowers   accomplish by multiplying a and b by a power of 2.  The exponent
31955697Smcpowers   (shift count) is placed in *pd, so that the remainder can be shifted
31965697Smcpowers   back at the end of the division process.
31975697Smcpowers  */
31985697Smcpowers 
s_mp_norm(mp_int * a,mp_int * b,mp_digit * pd)31995697Smcpowers mp_err   s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd)
32005697Smcpowers {
32015697Smcpowers   mp_digit  d;
32025697Smcpowers   mp_digit  mask;
32035697Smcpowers   mp_digit  b_msd;
32045697Smcpowers   mp_err    res    = MP_OKAY;
32055697Smcpowers 
32065697Smcpowers   d = 0;
32075697Smcpowers   mask  = DIGIT_MAX & ~(DIGIT_MAX >> 1);	/* mask is msb of digit */
32085697Smcpowers   b_msd = DIGIT(b, USED(b) - 1);
32095697Smcpowers   while (!(b_msd & mask)) {
32105697Smcpowers     b_msd <<= 1;
32115697Smcpowers     ++d;
32125697Smcpowers   }
32135697Smcpowers 
32145697Smcpowers   if (d) {
32155697Smcpowers     MP_CHECKOK( s_mp_mul_2d(a, d) );
32165697Smcpowers     MP_CHECKOK( s_mp_mul_2d(b, d) );
32175697Smcpowers   }
32185697Smcpowers 
32195697Smcpowers   *pd = d;
32205697Smcpowers CLEANUP:
32215697Smcpowers   return res;
32225697Smcpowers 
32235697Smcpowers } /* end s_mp_norm() */
32245697Smcpowers 
32255697Smcpowers /* }}} */
32265697Smcpowers 
32275697Smcpowers /* }}} */
32285697Smcpowers 
32295697Smcpowers /* {{{ Primitive digit arithmetic */
32305697Smcpowers 
32315697Smcpowers /* {{{ s_mp_add_d(mp, d) */
32325697Smcpowers 
32335697Smcpowers /* Add d to |mp| in place                                                 */
s_mp_add_d(mp_int * mp,mp_digit d)32345697Smcpowers mp_err   s_mp_add_d(mp_int *mp, mp_digit d)    /* unsigned digit addition */
32355697Smcpowers {
32365697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
32375697Smcpowers   mp_word   w, k = 0;
32385697Smcpowers   mp_size   ix = 1;
32395697Smcpowers 
32405697Smcpowers   w = (mp_word)DIGIT(mp, 0) + d;
32415697Smcpowers   DIGIT(mp, 0) = ACCUM(w);
32425697Smcpowers   k = CARRYOUT(w);
32435697Smcpowers 
32445697Smcpowers   while(ix < USED(mp) && k) {
32455697Smcpowers     w = (mp_word)DIGIT(mp, ix) + k;
32465697Smcpowers     DIGIT(mp, ix) = ACCUM(w);
32475697Smcpowers     k = CARRYOUT(w);
32485697Smcpowers     ++ix;
32495697Smcpowers   }
32505697Smcpowers 
32515697Smcpowers   if(k != 0) {
32525697Smcpowers     mp_err  res;
32535697Smcpowers 
32545697Smcpowers     if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)
32555697Smcpowers       return res;
32565697Smcpowers 
32575697Smcpowers     DIGIT(mp, ix) = (mp_digit)k;
32585697Smcpowers   }
32595697Smcpowers 
32605697Smcpowers   return MP_OKAY;
32615697Smcpowers #else
32625697Smcpowers   mp_digit * pmp = MP_DIGITS(mp);
32635697Smcpowers   mp_digit sum, mp_i, carry = 0;
32645697Smcpowers   mp_err   res = MP_OKAY;
32655697Smcpowers   int used = (int)MP_USED(mp);
32665697Smcpowers 
32675697Smcpowers   mp_i = *pmp;
32685697Smcpowers   *pmp++ = sum = d + mp_i;
32695697Smcpowers   carry = (sum < d);
32705697Smcpowers   while (carry && --used > 0) {
32715697Smcpowers     mp_i = *pmp;
32725697Smcpowers     *pmp++ = sum = carry + mp_i;
32735697Smcpowers     carry = !sum;
32745697Smcpowers   }
32755697Smcpowers   if (carry && !used) {
32765697Smcpowers     /* mp is growing */
32775697Smcpowers     used = MP_USED(mp);
32785697Smcpowers     MP_CHECKOK( s_mp_pad(mp, used + 1) );
32795697Smcpowers     MP_DIGIT(mp, used) = carry;
32805697Smcpowers   }
32815697Smcpowers CLEANUP:
32825697Smcpowers   return res;
32835697Smcpowers #endif
32845697Smcpowers } /* end s_mp_add_d() */
32855697Smcpowers 
32865697Smcpowers /* }}} */
32875697Smcpowers 
32885697Smcpowers /* {{{ s_mp_sub_d(mp, d) */
32895697Smcpowers 
32905697Smcpowers /* Subtract d from |mp| in place, assumes |mp| > d                        */
s_mp_sub_d(mp_int * mp,mp_digit d)32915697Smcpowers mp_err   s_mp_sub_d(mp_int *mp, mp_digit d)    /* unsigned digit subtract */
32925697Smcpowers {
32935697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
32945697Smcpowers   mp_word   w, b = 0;
32955697Smcpowers   mp_size   ix = 1;
32965697Smcpowers 
32975697Smcpowers   /* Compute initial subtraction    */
32985697Smcpowers   w = (RADIX + (mp_word)DIGIT(mp, 0)) - d;
32995697Smcpowers   b = CARRYOUT(w) ? 0 : 1;
33005697Smcpowers   DIGIT(mp, 0) = ACCUM(w);
33015697Smcpowers 
33025697Smcpowers   /* Propagate borrows leftward     */
33035697Smcpowers   while(b && ix < USED(mp)) {
33045697Smcpowers     w = (RADIX + (mp_word)DIGIT(mp, ix)) - b;
33055697Smcpowers     b = CARRYOUT(w) ? 0 : 1;
33065697Smcpowers     DIGIT(mp, ix) = ACCUM(w);
33075697Smcpowers     ++ix;
33085697Smcpowers   }
33095697Smcpowers 
33105697Smcpowers   /* Remove leading zeroes          */
33115697Smcpowers   s_mp_clamp(mp);
33125697Smcpowers 
33135697Smcpowers   /* If we have a borrow out, it's a violation of the input invariant */
33145697Smcpowers   if(b)
33155697Smcpowers     return MP_RANGE;
33165697Smcpowers   else
33175697Smcpowers     return MP_OKAY;
33185697Smcpowers #else
33195697Smcpowers   mp_digit *pmp = MP_DIGITS(mp);
33205697Smcpowers   mp_digit mp_i, diff, borrow;
33215697Smcpowers   mp_size  used = MP_USED(mp);
33225697Smcpowers 
33235697Smcpowers   mp_i = *pmp;
33245697Smcpowers   *pmp++ = diff = mp_i - d;
33255697Smcpowers   borrow = (diff > mp_i);
33265697Smcpowers   while (borrow && --used) {
33275697Smcpowers     mp_i = *pmp;
33285697Smcpowers     *pmp++ = diff = mp_i - borrow;
33295697Smcpowers     borrow = (diff > mp_i);
33305697Smcpowers   }
33315697Smcpowers   s_mp_clamp(mp);
33325697Smcpowers   return (borrow && !used) ? MP_RANGE : MP_OKAY;
33335697Smcpowers #endif
33345697Smcpowers } /* end s_mp_sub_d() */
33355697Smcpowers 
33365697Smcpowers /* }}} */
33375697Smcpowers 
33385697Smcpowers /* {{{ s_mp_mul_d(a, d) */
33395697Smcpowers 
33405697Smcpowers /* Compute a = a * d, single digit multiplication                         */
s_mp_mul_d(mp_int * a,mp_digit d)33415697Smcpowers mp_err   s_mp_mul_d(mp_int *a, mp_digit d)
33425697Smcpowers {
33435697Smcpowers   mp_err  res;
33445697Smcpowers   mp_size used;
33455697Smcpowers   int     pow;
33465697Smcpowers 
33475697Smcpowers   if (!d) {
33485697Smcpowers     mp_zero(a);
33495697Smcpowers     return MP_OKAY;
33505697Smcpowers   }
33515697Smcpowers   if (d == 1)
33525697Smcpowers     return MP_OKAY;
33535697Smcpowers   if (0 <= (pow = s_mp_ispow2d(d))) {
33545697Smcpowers     return s_mp_mul_2d(a, (mp_digit)pow);
33555697Smcpowers   }
33565697Smcpowers 
33575697Smcpowers   used = MP_USED(a);
33585697Smcpowers   MP_CHECKOK( s_mp_pad(a, used + 1) );
33595697Smcpowers 
33605697Smcpowers   s_mpv_mul_d(MP_DIGITS(a), used, d, MP_DIGITS(a));
33615697Smcpowers 
33625697Smcpowers   s_mp_clamp(a);
33635697Smcpowers 
33645697Smcpowers CLEANUP:
33655697Smcpowers   return res;
33665697Smcpowers 
33675697Smcpowers } /* end s_mp_mul_d() */
33685697Smcpowers 
33695697Smcpowers /* }}} */
33705697Smcpowers 
33715697Smcpowers /* {{{ s_mp_div_d(mp, d, r) */
33725697Smcpowers 
33735697Smcpowers /*
33745697Smcpowers   s_mp_div_d(mp, d, r)
33755697Smcpowers 
33765697Smcpowers   Compute the quotient mp = mp / d and remainder r = mp mod d, for a
33775697Smcpowers   single digit d.  If r is null, the remainder will be discarded.
33785697Smcpowers  */
33795697Smcpowers 
s_mp_div_d(mp_int * mp,mp_digit d,mp_digit * r)33805697Smcpowers mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
33815697Smcpowers {
33825697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
33835697Smcpowers   mp_word   w = 0, q;
33845697Smcpowers #else
33855697Smcpowers   mp_digit  w, q;
33865697Smcpowers #endif
33875697Smcpowers   int       ix;
33885697Smcpowers   mp_err    res;
33895697Smcpowers   mp_int    quot;
33905697Smcpowers   mp_int    rem;
33915697Smcpowers 
33925697Smcpowers   if(d == 0)
33935697Smcpowers     return MP_RANGE;
33945697Smcpowers   if (d == 1) {
33955697Smcpowers     if (r)
33965697Smcpowers       *r = 0;
33975697Smcpowers     return MP_OKAY;
33985697Smcpowers   }
33995697Smcpowers   /* could check for power of 2 here, but mp_div_d does that. */
34005697Smcpowers   if (MP_USED(mp) == 1) {
34015697Smcpowers     mp_digit n   = MP_DIGIT(mp,0);
34025697Smcpowers     mp_digit rem;
34035697Smcpowers 
34045697Smcpowers     q   = n / d;
34055697Smcpowers     rem = n % d;
34065697Smcpowers     MP_DIGIT(mp,0) = q;
34075697Smcpowers     if (r)
34085697Smcpowers       *r = rem;
34095697Smcpowers     return MP_OKAY;
34105697Smcpowers   }
34115697Smcpowers 
34125697Smcpowers   MP_DIGITS(&rem)  = 0;
34135697Smcpowers   MP_DIGITS(&quot) = 0;
34145697Smcpowers   /* Make room for the quotient */
34155697Smcpowers   MP_CHECKOK( mp_init_size(&quot, USED(mp), FLAG(mp)) );
34165697Smcpowers 
34175697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
34185697Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
34195697Smcpowers     w = (w << DIGIT_BIT) | DIGIT(mp, ix);
34205697Smcpowers 
34215697Smcpowers     if(w >= d) {
34225697Smcpowers       q = w / d;
34235697Smcpowers       w = w % d;
34245697Smcpowers     } else {
34255697Smcpowers       q = 0;
34265697Smcpowers     }
34275697Smcpowers 
34285697Smcpowers     s_mp_lshd(&quot, 1);
34295697Smcpowers     DIGIT(&quot, 0) = (mp_digit)q;
34305697Smcpowers   }
34315697Smcpowers #else
34325697Smcpowers   {
34335697Smcpowers     mp_digit p;
34345697Smcpowers #if !defined(MP_ASSEMBLY_DIV_2DX1D)
34355697Smcpowers     mp_digit norm;
34365697Smcpowers #endif
34375697Smcpowers 
34385697Smcpowers     MP_CHECKOK( mp_init_copy(&rem, mp) );
34395697Smcpowers 
34405697Smcpowers #if !defined(MP_ASSEMBLY_DIV_2DX1D)
34415697Smcpowers     MP_DIGIT(&quot, 0) = d;
34425697Smcpowers     MP_CHECKOK( s_mp_norm(&rem, &quot, &norm) );
34435697Smcpowers     if (norm)
34445697Smcpowers       d <<= norm;
34455697Smcpowers     MP_DIGIT(&quot, 0) = 0;
34465697Smcpowers #endif
34475697Smcpowers 
34485697Smcpowers     p = 0;
34495697Smcpowers     for (ix = USED(&rem) - 1; ix >= 0; ix--) {
34505697Smcpowers       w = DIGIT(&rem, ix);
34515697Smcpowers 
34525697Smcpowers       if (p) {
34535697Smcpowers         MP_CHECKOK( s_mpv_div_2dx1d(p, w, d, &q, &w) );
34545697Smcpowers       } else if (w >= d) {
34555697Smcpowers 	q = w / d;
34565697Smcpowers 	w = w % d;
34575697Smcpowers       } else {
34585697Smcpowers 	q = 0;
34595697Smcpowers       }
34605697Smcpowers 
34615697Smcpowers       MP_CHECKOK( s_mp_lshd(&quot, 1) );
34625697Smcpowers       DIGIT(&quot, 0) = q;
34635697Smcpowers       p = w;
34645697Smcpowers     }
34655697Smcpowers #if !defined(MP_ASSEMBLY_DIV_2DX1D)
34665697Smcpowers     if (norm)
34675697Smcpowers       w >>= norm;
34685697Smcpowers #endif
34695697Smcpowers   }
34705697Smcpowers #endif
34715697Smcpowers 
34725697Smcpowers   /* Deliver the remainder, if desired */
34735697Smcpowers   if(r)
34745697Smcpowers     *r = (mp_digit)w;
34755697Smcpowers 
34765697Smcpowers   s_mp_clamp(&quot);
34775697Smcpowers   mp_exch(&quot, mp);
34785697Smcpowers CLEANUP:
34795697Smcpowers   mp_clear(&quot);
34805697Smcpowers   mp_clear(&rem);
34815697Smcpowers 
34825697Smcpowers   return res;
34835697Smcpowers } /* end s_mp_div_d() */
34845697Smcpowers 
34855697Smcpowers /* }}} */
34865697Smcpowers 
34875697Smcpowers 
34885697Smcpowers /* }}} */
34895697Smcpowers 
34905697Smcpowers /* {{{ Primitive full arithmetic */
34915697Smcpowers 
34925697Smcpowers /* {{{ s_mp_add(a, b) */
34935697Smcpowers 
34945697Smcpowers /* Compute a = |a| + |b|                                                  */
s_mp_add(mp_int * a,const mp_int * b)34955697Smcpowers mp_err   s_mp_add(mp_int *a, const mp_int *b)  /* magnitude addition      */
34965697Smcpowers {
34975697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
34985697Smcpowers   mp_word   w = 0;
34995697Smcpowers #else
35005697Smcpowers   mp_digit  d, sum, carry = 0;
35015697Smcpowers #endif
35025697Smcpowers   mp_digit *pa, *pb;
35035697Smcpowers   mp_size   ix;
35045697Smcpowers   mp_size   used;
35055697Smcpowers   mp_err    res;
35065697Smcpowers 
35075697Smcpowers   /* Make sure a has enough precision for the output value */
35085697Smcpowers   if((USED(b) > USED(a)) && (res = s_mp_pad(a, USED(b))) != MP_OKAY)
35095697Smcpowers     return res;
35105697Smcpowers 
35115697Smcpowers   /*
35125697Smcpowers     Add up all digits up to the precision of b.  If b had initially
35135697Smcpowers     the same precision as a, or greater, we took care of it by the
35145697Smcpowers     padding step above, so there is no problem.  If b had initially
35155697Smcpowers     less precision, we'll have to make sure the carry out is duly
35165697Smcpowers     propagated upward among the higher-order digits of the sum.
35175697Smcpowers    */
35185697Smcpowers   pa = MP_DIGITS(a);
35195697Smcpowers   pb = MP_DIGITS(b);
35205697Smcpowers   used = MP_USED(b);
35215697Smcpowers   for(ix = 0; ix < used; ix++) {
35225697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
35235697Smcpowers     w = w + *pa + *pb++;
35245697Smcpowers     *pa++ = ACCUM(w);
35255697Smcpowers     w = CARRYOUT(w);
35265697Smcpowers #else
35275697Smcpowers     d = *pa;
35285697Smcpowers     sum = d + *pb++;
35295697Smcpowers     d = (sum < d);			/* detect overflow */
35305697Smcpowers     *pa++ = sum += carry;
35315697Smcpowers     carry = d + (sum < carry);		/* detect overflow */
35325697Smcpowers #endif
35335697Smcpowers   }
35345697Smcpowers 
35355697Smcpowers   /* If we run out of 'b' digits before we're actually done, make
35365697Smcpowers      sure the carries get propagated upward...
35375697Smcpowers    */
35385697Smcpowers   used = MP_USED(a);
35395697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
35405697Smcpowers   while (w && ix < used) {
35415697Smcpowers     w = w + *pa;
35425697Smcpowers     *pa++ = ACCUM(w);
35435697Smcpowers     w = CARRYOUT(w);
35445697Smcpowers     ++ix;
35455697Smcpowers   }
35465697Smcpowers #else
35475697Smcpowers   while (carry && ix < used) {
35485697Smcpowers     sum = carry + *pa;
35495697Smcpowers     *pa++ = sum;
35505697Smcpowers     carry = !sum;
35515697Smcpowers     ++ix;
35525697Smcpowers   }
35535697Smcpowers #endif
35545697Smcpowers 
35555697Smcpowers   /* If there's an overall carry out, increase precision and include
35565697Smcpowers      it.  We could have done this initially, but why touch the memory
35575697Smcpowers      allocator unless we're sure we have to?
35585697Smcpowers    */
35595697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
35605697Smcpowers   if (w) {
35615697Smcpowers     if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
35625697Smcpowers       return res;
35635697Smcpowers 
35645697Smcpowers     DIGIT(a, ix) = (mp_digit)w;
35655697Smcpowers   }
35665697Smcpowers #else
35675697Smcpowers   if (carry) {
35685697Smcpowers     if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
35695697Smcpowers       return res;
35705697Smcpowers 
35715697Smcpowers     DIGIT(a, used) = carry;
35725697Smcpowers   }
35735697Smcpowers #endif
35745697Smcpowers 
35755697Smcpowers   return MP_OKAY;
35765697Smcpowers } /* end s_mp_add() */
35775697Smcpowers 
35785697Smcpowers /* }}} */
35795697Smcpowers 
35805697Smcpowers /* Compute c = |a| + |b|         */ /* magnitude addition      */
s_mp_add_3arg(const mp_int * a,const mp_int * b,mp_int * c)35815697Smcpowers mp_err   s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c)
35825697Smcpowers {
35835697Smcpowers   mp_digit *pa, *pb, *pc;
35845697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
35855697Smcpowers   mp_word   w = 0;
35865697Smcpowers #else
35875697Smcpowers   mp_digit  sum, carry = 0, d;
35885697Smcpowers #endif
35895697Smcpowers   mp_size   ix;
35905697Smcpowers   mp_size   used;
35915697Smcpowers   mp_err    res;
35925697Smcpowers 
35935697Smcpowers   MP_SIGN(c) = MP_SIGN(a);
35945697Smcpowers   if (MP_USED(a) < MP_USED(b)) {
35955697Smcpowers     const mp_int *xch = a;
35965697Smcpowers     a = b;
35975697Smcpowers     b = xch;
35985697Smcpowers   }
35995697Smcpowers 
36005697Smcpowers   /* Make sure a has enough precision for the output value */
36015697Smcpowers   if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a))))
36025697Smcpowers     return res;
36035697Smcpowers 
36045697Smcpowers   /*
36055697Smcpowers     Add up all digits up to the precision of b.  If b had initially
36065697Smcpowers     the same precision as a, or greater, we took care of it by the
36075697Smcpowers     exchange step above, so there is no problem.  If b had initially
36085697Smcpowers     less precision, we'll have to make sure the carry out is duly
36095697Smcpowers     propagated upward among the higher-order digits of the sum.
36105697Smcpowers    */
36115697Smcpowers   pa = MP_DIGITS(a);
36125697Smcpowers   pb = MP_DIGITS(b);
36135697Smcpowers   pc = MP_DIGITS(c);
36145697Smcpowers   used = MP_USED(b);
36155697Smcpowers   for (ix = 0; ix < used; ix++) {
36165697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
36175697Smcpowers     w = w + *pa++ + *pb++;
36185697Smcpowers     *pc++ = ACCUM(w);
36195697Smcpowers     w = CARRYOUT(w);
36205697Smcpowers #else
36215697Smcpowers     d = *pa++;
36225697Smcpowers     sum = d + *pb++;
36235697Smcpowers     d = (sum < d);			/* detect overflow */
36245697Smcpowers     *pc++ = sum += carry;
36255697Smcpowers     carry = d + (sum < carry);		/* detect overflow */
36265697Smcpowers #endif
36275697Smcpowers   }
36285697Smcpowers 
36295697Smcpowers   /* If we run out of 'b' digits before we're actually done, make
36305697Smcpowers      sure the carries get propagated upward...
36315697Smcpowers    */
36325697Smcpowers   for (used = MP_USED(a); ix < used; ++ix) {
36335697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
36345697Smcpowers     w = w + *pa++;
36355697Smcpowers     *pc++ = ACCUM(w);
36365697Smcpowers     w = CARRYOUT(w);
36375697Smcpowers #else
36385697Smcpowers     *pc++ = sum = carry + *pa++;
36395697Smcpowers     carry = (sum < carry);
36405697Smcpowers #endif
36415697Smcpowers   }
36425697Smcpowers 
36435697Smcpowers   /* If there's an overall carry out, increase precision and include
36445697Smcpowers      it.  We could have done this initially, but why touch the memory
36455697Smcpowers      allocator unless we're sure we have to?
36465697Smcpowers    */
36475697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
36485697Smcpowers   if (w) {
36495697Smcpowers     if((res = s_mp_pad(c, used + 1)) != MP_OKAY)
36505697Smcpowers       return res;
36515697Smcpowers 
36525697Smcpowers     DIGIT(c, used) = (mp_digit)w;
36535697Smcpowers     ++used;
36545697Smcpowers   }
36555697Smcpowers #else
36565697Smcpowers   if (carry) {
36575697Smcpowers     if((res = s_mp_pad(c, used + 1)) != MP_OKAY)
36585697Smcpowers       return res;
36595697Smcpowers 
36605697Smcpowers     DIGIT(c, used) = carry;
36615697Smcpowers     ++used;
36625697Smcpowers   }
36635697Smcpowers #endif
36645697Smcpowers   MP_USED(c) = used;
36655697Smcpowers   return MP_OKAY;
36665697Smcpowers }
36675697Smcpowers /* {{{ s_mp_add_offset(a, b, offset) */
36685697Smcpowers 
36695697Smcpowers /* Compute a = |a| + ( |b| * (RADIX ** offset) )             */
s_mp_add_offset(mp_int * a,mp_int * b,mp_size offset)36705697Smcpowers mp_err   s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset)
36715697Smcpowers {
36725697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
36735697Smcpowers   mp_word   w, k = 0;
36745697Smcpowers #else
36755697Smcpowers   mp_digit  d, sum, carry = 0;
36765697Smcpowers #endif
36775697Smcpowers   mp_size   ib;
36785697Smcpowers   mp_size   ia;
36795697Smcpowers   mp_size   lim;
36805697Smcpowers   mp_err    res;
36815697Smcpowers 
36825697Smcpowers   /* Make sure a has enough precision for the output value */
36835697Smcpowers   lim = MP_USED(b) + offset;
36845697Smcpowers   if((lim > USED(a)) && (res = s_mp_pad(a, lim)) != MP_OKAY)
36855697Smcpowers     return res;
36865697Smcpowers 
36875697Smcpowers   /*
36885697Smcpowers     Add up all digits up to the precision of b.  If b had initially
36895697Smcpowers     the same precision as a, or greater, we took care of it by the
36905697Smcpowers     padding step above, so there is no problem.  If b had initially
36915697Smcpowers     less precision, we'll have to make sure the carry out is duly
36925697Smcpowers     propagated upward among the higher-order digits of the sum.
36935697Smcpowers    */
36945697Smcpowers   lim = USED(b);
36955697Smcpowers   for(ib = 0, ia = offset; ib < lim; ib++, ia++) {
36965697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
36975697Smcpowers     w = (mp_word)DIGIT(a, ia) + DIGIT(b, ib) + k;
36985697Smcpowers     DIGIT(a, ia) = ACCUM(w);
36995697Smcpowers     k = CARRYOUT(w);
37005697Smcpowers #else
37015697Smcpowers     d = MP_DIGIT(a, ia);
37025697Smcpowers     sum = d + MP_DIGIT(b, ib);
37035697Smcpowers     d = (sum < d);
37045697Smcpowers     MP_DIGIT(a,ia) = sum += carry;
37055697Smcpowers     carry = d + (sum < carry);
37065697Smcpowers #endif
37075697Smcpowers   }
37085697Smcpowers 
37095697Smcpowers   /* If we run out of 'b' digits before we're actually done, make
37105697Smcpowers      sure the carries get propagated upward...
37115697Smcpowers    */
37125697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
37135697Smcpowers   for (lim = MP_USED(a); k && (ia < lim); ++ia) {
37145697Smcpowers     w = (mp_word)DIGIT(a, ia) + k;
37155697Smcpowers     DIGIT(a, ia) = ACCUM(w);
37165697Smcpowers     k = CARRYOUT(w);
37175697Smcpowers   }
37185697Smcpowers #else
37195697Smcpowers   for (lim = MP_USED(a); carry && (ia < lim); ++ia) {
37205697Smcpowers     d = MP_DIGIT(a, ia);
37215697Smcpowers     MP_DIGIT(a,ia) = sum = d + carry;
37225697Smcpowers     carry = (sum < d);
37235697Smcpowers   }
37245697Smcpowers #endif
37255697Smcpowers 
37265697Smcpowers   /* If there's an overall carry out, increase precision and include
37275697Smcpowers      it.  We could have done this initially, but why touch the memory
37285697Smcpowers      allocator unless we're sure we have to?
37295697Smcpowers    */
37305697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
37315697Smcpowers   if(k) {
37325697Smcpowers     if((res = s_mp_pad(a, USED(a) + 1)) != MP_OKAY)
37335697Smcpowers       return res;
37345697Smcpowers 
37355697Smcpowers     DIGIT(a, ia) = (mp_digit)k;
37365697Smcpowers   }
37375697Smcpowers #else
37385697Smcpowers   if (carry) {
37395697Smcpowers     if((res = s_mp_pad(a, lim + 1)) != MP_OKAY)
37405697Smcpowers       return res;
37415697Smcpowers 
37425697Smcpowers     DIGIT(a, lim) = carry;
37435697Smcpowers   }
37445697Smcpowers #endif
37455697Smcpowers   s_mp_clamp(a);
37465697Smcpowers 
37475697Smcpowers   return MP_OKAY;
37485697Smcpowers 
37495697Smcpowers } /* end s_mp_add_offset() */
37505697Smcpowers 
37515697Smcpowers /* }}} */
37525697Smcpowers 
37535697Smcpowers /* {{{ s_mp_sub(a, b) */
37545697Smcpowers 
37555697Smcpowers /* Compute a = |a| - |b|, assumes |a| >= |b|                              */
s_mp_sub(mp_int * a,const mp_int * b)37565697Smcpowers mp_err   s_mp_sub(mp_int *a, const mp_int *b)  /* magnitude subtract      */
37575697Smcpowers {
37585697Smcpowers   mp_digit *pa, *pb, *limit;
37595697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
37605697Smcpowers   mp_sword  w = 0;
37615697Smcpowers #else
37625697Smcpowers   mp_digit  d, diff, borrow = 0;
37635697Smcpowers #endif
37645697Smcpowers 
37655697Smcpowers   /*
37665697Smcpowers     Subtract and propagate borrow.  Up to the precision of b, this
37675697Smcpowers     accounts for the digits of b; after that, we just make sure the
37685697Smcpowers     carries get to the right place.  This saves having to pad b out to
37695697Smcpowers     the precision of a just to make the loops work right...
37705697Smcpowers    */
37715697Smcpowers   pa = MP_DIGITS(a);
37725697Smcpowers   pb = MP_DIGITS(b);
37735697Smcpowers   limit = pb + MP_USED(b);
37745697Smcpowers   while (pb < limit) {
37755697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
37765697Smcpowers     w = w + *pa - *pb++;
37775697Smcpowers     *pa++ = ACCUM(w);
37785697Smcpowers     w >>= MP_DIGIT_BIT;
37795697Smcpowers #else
37805697Smcpowers     d = *pa;
37815697Smcpowers     diff = d - *pb++;
37825697Smcpowers     d = (diff > d);				/* detect borrow */
37835697Smcpowers     if (borrow && --diff == MP_DIGIT_MAX)
37845697Smcpowers       ++d;
37855697Smcpowers     *pa++ = diff;
37865697Smcpowers     borrow = d;
37875697Smcpowers #endif
37885697Smcpowers   }
37895697Smcpowers   limit = MP_DIGITS(a) + MP_USED(a);
37905697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
37915697Smcpowers   while (w && pa < limit) {
37925697Smcpowers     w = w + *pa;
37935697Smcpowers     *pa++ = ACCUM(w);
37945697Smcpowers     w >>= MP_DIGIT_BIT;
37955697Smcpowers   }
37965697Smcpowers #else
37975697Smcpowers   while (borrow && pa < limit) {
37985697Smcpowers     d = *pa;
37995697Smcpowers     *pa++ = diff = d - borrow;
38005697Smcpowers     borrow = (diff > d);
38015697Smcpowers   }
38025697Smcpowers #endif
38035697Smcpowers 
38045697Smcpowers   /* Clobber any leading zeroes we created    */
38055697Smcpowers   s_mp_clamp(a);
38065697Smcpowers 
38075697Smcpowers   /*
38085697Smcpowers      If there was a borrow out, then |b| > |a| in violation
38095697Smcpowers      of our input invariant.  We've already done the work,
38105697Smcpowers      but we'll at least complain about it...
38115697Smcpowers    */
38125697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
38135697Smcpowers   return w ? MP_RANGE : MP_OKAY;
38145697Smcpowers #else
38155697Smcpowers   return borrow ? MP_RANGE : MP_OKAY;
38165697Smcpowers #endif
38175697Smcpowers } /* end s_mp_sub() */
38185697Smcpowers 
38195697Smcpowers /* }}} */
38205697Smcpowers 
38215697Smcpowers /* Compute c = |a| - |b|, assumes |a| >= |b| */ /* magnitude subtract      */
s_mp_sub_3arg(const mp_int * a,const mp_int * b,mp_int * c)38225697Smcpowers mp_err   s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c)
38235697Smcpowers {
38245697Smcpowers   mp_digit *pa, *pb, *pc;
38255697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
38265697Smcpowers   mp_sword  w = 0;
38275697Smcpowers #else
38285697Smcpowers   mp_digit  d, diff, borrow = 0;
38295697Smcpowers #endif
38305697Smcpowers   int       ix, limit;
38315697Smcpowers   mp_err    res;
38325697Smcpowers 
38335697Smcpowers   MP_SIGN(c) = MP_SIGN(a);
38345697Smcpowers 
38355697Smcpowers   /* Make sure a has enough precision for the output value */
38365697Smcpowers   if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a))))
38375697Smcpowers     return res;
38385697Smcpowers 
38395697Smcpowers   /*
38405697Smcpowers     Subtract and propagate borrow.  Up to the precision of b, this
38415697Smcpowers     accounts for the digits of b; after that, we just make sure the
38425697Smcpowers     carries get to the right place.  This saves having to pad b out to
38435697Smcpowers     the precision of a just to make the loops work right...
38445697Smcpowers    */
38455697Smcpowers   pa = MP_DIGITS(a);
38465697Smcpowers   pb = MP_DIGITS(b);
38475697Smcpowers   pc = MP_DIGITS(c);
38485697Smcpowers   limit = MP_USED(b);
38495697Smcpowers   for (ix = 0; ix < limit; ++ix) {
38505697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
38515697Smcpowers     w = w + *pa++ - *pb++;
38525697Smcpowers     *pc++ = ACCUM(w);
38535697Smcpowers     w >>= MP_DIGIT_BIT;
38545697Smcpowers #else
38555697Smcpowers     d = *pa++;
38565697Smcpowers     diff = d - *pb++;
38575697Smcpowers     d = (diff > d);
38585697Smcpowers     if (borrow && --diff == MP_DIGIT_MAX)
38595697Smcpowers       ++d;
38605697Smcpowers     *pc++ = diff;
38615697Smcpowers     borrow = d;
38625697Smcpowers #endif
38635697Smcpowers   }
38645697Smcpowers   for (limit = MP_USED(a); ix < limit; ++ix) {
38655697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
38665697Smcpowers     w = w + *pa++;
38675697Smcpowers     *pc++ = ACCUM(w);
38685697Smcpowers     w >>= MP_DIGIT_BIT;
38695697Smcpowers #else
38705697Smcpowers     d = *pa++;
38715697Smcpowers     *pc++ = diff = d - borrow;
38725697Smcpowers     borrow = (diff > d);
38735697Smcpowers #endif
38745697Smcpowers   }
38755697Smcpowers 
38765697Smcpowers   /* Clobber any leading zeroes we created    */
38775697Smcpowers   MP_USED(c) = ix;
38785697Smcpowers   s_mp_clamp(c);
38795697Smcpowers 
38805697Smcpowers   /*
38815697Smcpowers      If there was a borrow out, then |b| > |a| in violation
38825697Smcpowers      of our input invariant.  We've already done the work,
38835697Smcpowers      but we'll at least complain about it...
38845697Smcpowers    */
38855697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
38865697Smcpowers   return w ? MP_RANGE : MP_OKAY;
38875697Smcpowers #else
38885697Smcpowers   return borrow ? MP_RANGE : MP_OKAY;
38895697Smcpowers #endif
38905697Smcpowers }
38915697Smcpowers /* {{{ s_mp_mul(a, b) */
38925697Smcpowers 
38935697Smcpowers /* Compute a = |a| * |b|                                                  */
s_mp_mul(mp_int * a,const mp_int * b)38945697Smcpowers mp_err   s_mp_mul(mp_int *a, const mp_int *b)
38955697Smcpowers {
38965697Smcpowers   return mp_mul(a, b, a);
38975697Smcpowers } /* end s_mp_mul() */
38985697Smcpowers 
38995697Smcpowers /* }}} */
39005697Smcpowers 
39015697Smcpowers #if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY)
39025697Smcpowers /* This trick works on Sparc V8 CPUs with the Workshop compilers. */
39035697Smcpowers #define MP_MUL_DxD(a, b, Phi, Plo) \
39045697Smcpowers   { unsigned long long product = (unsigned long long)a * b; \
39055697Smcpowers     Plo = (mp_digit)product; \
39065697Smcpowers     Phi = (mp_digit)(product >> MP_DIGIT_BIT); }
39075697Smcpowers #elif defined(OSF1)
39085697Smcpowers #define MP_MUL_DxD(a, b, Phi, Plo) \
39095697Smcpowers   { Plo = asm ("mulq %a0, %a1, %v0", a, b);\
39105697Smcpowers     Phi = asm ("umulh %a0, %a1, %v0", a, b); }
39115697Smcpowers #else
39125697Smcpowers #define MP_MUL_DxD(a, b, Phi, Plo) \
39135697Smcpowers   { mp_digit a0b1, a1b0; \
39145697Smcpowers     Plo = (a & MP_HALF_DIGIT_MAX) * (b & MP_HALF_DIGIT_MAX); \
39155697Smcpowers     Phi = (a >> MP_HALF_DIGIT_BIT) * (b >> MP_HALF_DIGIT_BIT); \
39165697Smcpowers     a0b1 = (a & MP_HALF_DIGIT_MAX) * (b >> MP_HALF_DIGIT_BIT); \
39175697Smcpowers     a1b0 = (a >> MP_HALF_DIGIT_BIT) * (b & MP_HALF_DIGIT_MAX); \
39185697Smcpowers     a1b0 += a0b1; \
39195697Smcpowers     Phi += a1b0 >> MP_HALF_DIGIT_BIT; \
39205697Smcpowers     if (a1b0 < a0b1)  \
39215697Smcpowers       Phi += MP_HALF_RADIX; \
39225697Smcpowers     a1b0 <<= MP_HALF_DIGIT_BIT; \
39235697Smcpowers     Plo += a1b0; \
39245697Smcpowers     if (Plo < a1b0) \
39255697Smcpowers       ++Phi; \
39265697Smcpowers   }
39275697Smcpowers #endif
39285697Smcpowers 
39295697Smcpowers #if !defined(MP_ASSEMBLY_MULTIPLY)
39305697Smcpowers /* c = a * b */
s_mpv_mul_d(const mp_digit * a,mp_size a_len,mp_digit b,mp_digit * c)39315697Smcpowers void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
39325697Smcpowers {
39335697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
39345697Smcpowers   mp_digit   d = 0;
39355697Smcpowers 
39365697Smcpowers   /* Inner product:  Digits of a */
39375697Smcpowers   while (a_len--) {
39385697Smcpowers     mp_word w = ((mp_word)b * *a++) + d;
39395697Smcpowers     *c++ = ACCUM(w);
39405697Smcpowers     d = CARRYOUT(w);
39415697Smcpowers   }
39425697Smcpowers   *c = d;
39435697Smcpowers #else
39445697Smcpowers   mp_digit carry = 0;
39455697Smcpowers   while (a_len--) {
39465697Smcpowers     mp_digit a_i = *a++;
39475697Smcpowers     mp_digit a0b0, a1b1;
39485697Smcpowers 
39495697Smcpowers     MP_MUL_DxD(a_i, b, a1b1, a0b0);
39505697Smcpowers 
39515697Smcpowers     a0b0 += carry;
39525697Smcpowers     if (a0b0 < carry)
39535697Smcpowers       ++a1b1;
39545697Smcpowers     *c++ = a0b0;
39555697Smcpowers     carry = a1b1;
39565697Smcpowers   }
39575697Smcpowers   *c = carry;
39585697Smcpowers #endif
39595697Smcpowers }
39605697Smcpowers 
39615697Smcpowers /* c += a * b */
s_mpv_mul_d_add(const mp_digit * a,mp_size a_len,mp_digit b,mp_digit * c)39625697Smcpowers void s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b,
39635697Smcpowers 			      mp_digit *c)
39645697Smcpowers {
39655697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
39665697Smcpowers   mp_digit   d = 0;
39675697Smcpowers 
39685697Smcpowers   /* Inner product:  Digits of a */
39695697Smcpowers   while (a_len--) {
39705697Smcpowers     mp_word w = ((mp_word)b * *a++) + *c + d;
39715697Smcpowers     *c++ = ACCUM(w);
39725697Smcpowers     d = CARRYOUT(w);
39735697Smcpowers   }
39745697Smcpowers   *c = d;
39755697Smcpowers #else
39765697Smcpowers   mp_digit carry = 0;
39775697Smcpowers   while (a_len--) {
39785697Smcpowers     mp_digit a_i = *a++;
39795697Smcpowers     mp_digit a0b0, a1b1;
39805697Smcpowers 
39815697Smcpowers     MP_MUL_DxD(a_i, b, a1b1, a0b0);
39825697Smcpowers 
39835697Smcpowers     a0b0 += carry;
39845697Smcpowers     if (a0b0 < carry)
39855697Smcpowers       ++a1b1;
39865697Smcpowers     a0b0 += a_i = *c;
39875697Smcpowers     if (a0b0 < a_i)
39885697Smcpowers       ++a1b1;
39895697Smcpowers     *c++ = a0b0;
39905697Smcpowers     carry = a1b1;
39915697Smcpowers   }
39925697Smcpowers   *c = carry;
39935697Smcpowers #endif
39945697Smcpowers }
39955697Smcpowers 
39965697Smcpowers /* Presently, this is only used by the Montgomery arithmetic code. */
39975697Smcpowers /* c += a * b */
s_mpv_mul_d_add_prop(const mp_digit * a,mp_size a_len,mp_digit b,mp_digit * c)39985697Smcpowers void s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
39995697Smcpowers {
40005697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
40015697Smcpowers   mp_digit   d = 0;
40025697Smcpowers 
40035697Smcpowers   /* Inner product:  Digits of a */
40045697Smcpowers   while (a_len--) {
40055697Smcpowers     mp_word w = ((mp_word)b * *a++) + *c + d;
40065697Smcpowers     *c++ = ACCUM(w);
40075697Smcpowers     d = CARRYOUT(w);
40085697Smcpowers   }
40095697Smcpowers 
40105697Smcpowers   while (d) {
40115697Smcpowers     mp_word w = (mp_word)*c + d;
40125697Smcpowers     *c++ = ACCUM(w);
40135697Smcpowers     d = CARRYOUT(w);
40145697Smcpowers   }
40155697Smcpowers #else
40165697Smcpowers   mp_digit carry = 0;
40175697Smcpowers   while (a_len--) {
40185697Smcpowers     mp_digit a_i = *a++;
40195697Smcpowers     mp_digit a0b0, a1b1;
40205697Smcpowers 
40215697Smcpowers     MP_MUL_DxD(a_i, b, a1b1, a0b0);
40225697Smcpowers 
40235697Smcpowers     a0b0 += carry;
40245697Smcpowers     if (a0b0 < carry)
40255697Smcpowers       ++a1b1;
40265697Smcpowers 
40275697Smcpowers     a0b0 += a_i = *c;
40285697Smcpowers     if (a0b0 < a_i)
40295697Smcpowers       ++a1b1;
40305697Smcpowers 
40315697Smcpowers     *c++ = a0b0;
40325697Smcpowers     carry = a1b1;
40335697Smcpowers   }
40345697Smcpowers   while (carry) {
40355697Smcpowers     mp_digit c_i = *c;
40365697Smcpowers     carry += c_i;
40375697Smcpowers     *c++ = carry;
40385697Smcpowers     carry = carry < c_i;
40395697Smcpowers   }
40405697Smcpowers #endif
40415697Smcpowers }
40425697Smcpowers #endif
40435697Smcpowers 
40445697Smcpowers #if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY)
40455697Smcpowers /* This trick works on Sparc V8 CPUs with the Workshop compilers. */
40465697Smcpowers #define MP_SQR_D(a, Phi, Plo) \
40475697Smcpowers   { unsigned long long square = (unsigned long long)a * a; \
40485697Smcpowers     Plo = (mp_digit)square; \
40495697Smcpowers     Phi = (mp_digit)(square >> MP_DIGIT_BIT); }
40505697Smcpowers #elif defined(OSF1)
40515697Smcpowers #define MP_SQR_D(a, Phi, Plo) \
40525697Smcpowers   { Plo = asm ("mulq  %a0, %a0, %v0", a);\
40535697Smcpowers     Phi = asm ("umulh %a0, %a0, %v0", a); }
40545697Smcpowers #else
40555697Smcpowers #define MP_SQR_D(a, Phi, Plo) \
40565697Smcpowers   { mp_digit Pmid; \
40575697Smcpowers     Plo  = (a  & MP_HALF_DIGIT_MAX) * (a  & MP_HALF_DIGIT_MAX); \
40585697Smcpowers     Phi  = (a >> MP_HALF_DIGIT_BIT) * (a >> MP_HALF_DIGIT_BIT); \
40595697Smcpowers     Pmid = (a  & MP_HALF_DIGIT_MAX) * (a >> MP_HALF_DIGIT_BIT); \
40605697Smcpowers     Phi += Pmid >> (MP_HALF_DIGIT_BIT - 1);  \
40615697Smcpowers     Pmid <<= (MP_HALF_DIGIT_BIT + 1);  \
40625697Smcpowers     Plo += Pmid;  \
40635697Smcpowers     if (Plo < Pmid)  \
40645697Smcpowers       ++Phi;  \
40655697Smcpowers   }
40665697Smcpowers #endif
40675697Smcpowers 
40685697Smcpowers #if !defined(MP_ASSEMBLY_SQUARE)
40695697Smcpowers /* Add the squares of the digits of a to the digits of b. */
s_mpv_sqr_add_prop(const mp_digit * pa,mp_size a_len,mp_digit * ps)40705697Smcpowers void s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
40715697Smcpowers {
40725697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
40735697Smcpowers   mp_word  w;
40745697Smcpowers   mp_digit d;
40755697Smcpowers   mp_size  ix;
40765697Smcpowers 
40775697Smcpowers   w  = 0;
40785697Smcpowers #define ADD_SQUARE(n) \
40795697Smcpowers     d = pa[n]; \
40805697Smcpowers     w += (d * (mp_word)d) + ps[2*n]; \
40815697Smcpowers     ps[2*n] = ACCUM(w); \
40825697Smcpowers     w = (w >> DIGIT_BIT) + ps[2*n+1]; \
40835697Smcpowers     ps[2*n+1] = ACCUM(w); \
40845697Smcpowers     w = (w >> DIGIT_BIT)
40855697Smcpowers 
40865697Smcpowers   for (ix = a_len; ix >= 4; ix -= 4) {
40875697Smcpowers     ADD_SQUARE(0);
40885697Smcpowers     ADD_SQUARE(1);
40895697Smcpowers     ADD_SQUARE(2);
40905697Smcpowers     ADD_SQUARE(3);
40915697Smcpowers     pa += 4;
40925697Smcpowers     ps += 8;
40935697Smcpowers   }
40945697Smcpowers   if (ix) {
40955697Smcpowers     ps += 2*ix;
40965697Smcpowers     pa += ix;
40975697Smcpowers     switch (ix) {
40985697Smcpowers     case 3: ADD_SQUARE(-3); /* FALLTHRU */
40995697Smcpowers     case 2: ADD_SQUARE(-2); /* FALLTHRU */
41005697Smcpowers     case 1: ADD_SQUARE(-1); /* FALLTHRU */
41015697Smcpowers     case 0: break;
41025697Smcpowers     }
41035697Smcpowers   }
41045697Smcpowers   while (w) {
41055697Smcpowers     w += *ps;
41065697Smcpowers     *ps++ = ACCUM(w);
41075697Smcpowers     w = (w >> DIGIT_BIT);
41085697Smcpowers   }
41095697Smcpowers #else
41105697Smcpowers   mp_digit carry = 0;
41115697Smcpowers   while (a_len--) {
41125697Smcpowers     mp_digit a_i = *pa++;
41135697Smcpowers     mp_digit a0a0, a1a1;
41145697Smcpowers 
41155697Smcpowers     MP_SQR_D(a_i, a1a1, a0a0);
41165697Smcpowers 
41175697Smcpowers     /* here a1a1 and a0a0 constitute a_i ** 2 */
41185697Smcpowers     a0a0 += carry;
41195697Smcpowers     if (a0a0 < carry)
41205697Smcpowers       ++a1a1;
41215697Smcpowers 
41225697Smcpowers     /* now add to ps */
41235697Smcpowers     a0a0 += a_i = *ps;
41245697Smcpowers     if (a0a0 < a_i)
41255697Smcpowers       ++a1a1;
41265697Smcpowers     *ps++ = a0a0;
41275697Smcpowers     a1a1 += a_i = *ps;
41285697Smcpowers     carry = (a1a1 < a_i);
41295697Smcpowers     *ps++ = a1a1;
41305697Smcpowers   }
41315697Smcpowers   while (carry) {
41325697Smcpowers     mp_digit s_i = *ps;
41335697Smcpowers     carry += s_i;
41345697Smcpowers     *ps++ = carry;
41355697Smcpowers     carry = carry < s_i;
41365697Smcpowers   }
41375697Smcpowers #endif
41385697Smcpowers }
41395697Smcpowers #endif
41405697Smcpowers 
41415697Smcpowers #if (defined(MP_NO_MP_WORD) || defined(MP_NO_DIV_WORD)) \
41425697Smcpowers && !defined(MP_ASSEMBLY_DIV_2DX1D)
41435697Smcpowers /*
41445697Smcpowers ** Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
41455697Smcpowers ** so its high bit is 1.   This code is from NSPR.
41465697Smcpowers */
s_mpv_div_2dx1d(mp_digit Nhi,mp_digit Nlo,mp_digit divisor,mp_digit * qp,mp_digit * rp)41475697Smcpowers mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
41485697Smcpowers 		       mp_digit *qp, mp_digit *rp)
41495697Smcpowers {
41505697Smcpowers     mp_digit d1, d0, q1, q0;
41515697Smcpowers     mp_digit r1, r0, m;
41525697Smcpowers 
41535697Smcpowers     d1 = divisor >> MP_HALF_DIGIT_BIT;
41545697Smcpowers     d0 = divisor & MP_HALF_DIGIT_MAX;
41555697Smcpowers     r1 = Nhi % d1;
41565697Smcpowers     q1 = Nhi / d1;
41575697Smcpowers     m = q1 * d0;
41585697Smcpowers     r1 = (r1 << MP_HALF_DIGIT_BIT) | (Nlo >> MP_HALF_DIGIT_BIT);
41595697Smcpowers     if (r1 < m) {
41605697Smcpowers         q1--, r1 += divisor;
41615697Smcpowers         if (r1 >= divisor && r1 < m) {
41625697Smcpowers 	    q1--, r1 += divisor;
41635697Smcpowers 	}
41645697Smcpowers     }
41655697Smcpowers     r1 -= m;
41665697Smcpowers     r0 = r1 % d1;
41675697Smcpowers     q0 = r1 / d1;
41685697Smcpowers     m = q0 * d0;
41695697Smcpowers     r0 = (r0 << MP_HALF_DIGIT_BIT) | (Nlo & MP_HALF_DIGIT_MAX);
41705697Smcpowers     if (r0 < m) {
41715697Smcpowers         q0--, r0 += divisor;
41725697Smcpowers         if (r0 >= divisor && r0 < m) {
41735697Smcpowers 	    q0--, r0 += divisor;
41745697Smcpowers 	}
41755697Smcpowers     }
41765697Smcpowers     if (qp)
41775697Smcpowers 	*qp = (q1 << MP_HALF_DIGIT_BIT) | q0;
41785697Smcpowers     if (rp)
41795697Smcpowers 	*rp = r0 - m;
41805697Smcpowers     return MP_OKAY;
41815697Smcpowers }
41825697Smcpowers #endif
41835697Smcpowers 
41845697Smcpowers #if MP_SQUARE
41855697Smcpowers /* {{{ s_mp_sqr(a) */
41865697Smcpowers 
s_mp_sqr(mp_int * a)41875697Smcpowers mp_err   s_mp_sqr(mp_int *a)
41885697Smcpowers {
41895697Smcpowers   mp_err   res;
41905697Smcpowers   mp_int   tmp;
41915697Smcpowers 
41925697Smcpowers   if((res = mp_init_size(&tmp, 2 * USED(a), FLAG(a))) != MP_OKAY)
41935697Smcpowers     return res;
41945697Smcpowers   res = mp_sqr(a, &tmp);
41955697Smcpowers   if (res == MP_OKAY) {
41965697Smcpowers     s_mp_exch(&tmp, a);
41975697Smcpowers   }
41985697Smcpowers   mp_clear(&tmp);
41995697Smcpowers   return res;
42005697Smcpowers }
42015697Smcpowers 
42025697Smcpowers /* }}} */
42035697Smcpowers #endif
42045697Smcpowers 
42055697Smcpowers /* {{{ s_mp_div(a, b) */
42065697Smcpowers 
42075697Smcpowers /*
42085697Smcpowers   s_mp_div(a, b)
42095697Smcpowers 
42105697Smcpowers   Compute a = a / b and b = a mod b.  Assumes b > a.
42115697Smcpowers  */
42125697Smcpowers 
s_mp_div(mp_int * rem,mp_int * div,mp_int * quot)42135697Smcpowers mp_err   s_mp_div(mp_int *rem, 	/* i: dividend, o: remainder */
42145697Smcpowers                   mp_int *div, 	/* i: divisor                */
42155697Smcpowers 		  mp_int *quot)	/* i: 0;        o: quotient  */
42165697Smcpowers {
42175697Smcpowers   mp_int   part, t;
42185697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
42195697Smcpowers   mp_word  q_msd;
42205697Smcpowers #else
42215697Smcpowers   mp_digit q_msd;
42225697Smcpowers #endif
42235697Smcpowers   mp_err   res;
42245697Smcpowers   mp_digit d;
42255697Smcpowers   mp_digit div_msd;
42265697Smcpowers   int      ix;
42275697Smcpowers 
42285697Smcpowers   if(mp_cmp_z(div) == 0)
42295697Smcpowers     return MP_RANGE;
42305697Smcpowers 
42315697Smcpowers   /* Shortcut if divisor is power of two */
42325697Smcpowers   if((ix = s_mp_ispow2(div)) >= 0) {
42335697Smcpowers     MP_CHECKOK( mp_copy(rem, quot) );
42345697Smcpowers     s_mp_div_2d(quot, (mp_digit)ix);
42355697Smcpowers     s_mp_mod_2d(rem,  (mp_digit)ix);
42365697Smcpowers 
42375697Smcpowers     return MP_OKAY;
42385697Smcpowers   }
42395697Smcpowers 
42405697Smcpowers   DIGITS(&t) = 0;
42415697Smcpowers   MP_SIGN(rem) = ZPOS;
42425697Smcpowers   MP_SIGN(div) = ZPOS;
42435697Smcpowers 
42445697Smcpowers   /* A working temporary for division     */
42455697Smcpowers   MP_CHECKOK( mp_init_size(&t, MP_ALLOC(rem), FLAG(rem)));
42465697Smcpowers 
42475697Smcpowers   /* Normalize to optimize guessing       */
42485697Smcpowers   MP_CHECKOK( s_mp_norm(rem, div, &d) );
42495697Smcpowers 
42505697Smcpowers   part = *rem;
42515697Smcpowers 
42525697Smcpowers   /* Perform the division itself...woo!   */
42535697Smcpowers   MP_USED(quot) = MP_ALLOC(quot);
42545697Smcpowers 
42555697Smcpowers   /* Find a partial substring of rem which is at least div */
42565697Smcpowers   /* If we didn't find one, we're finished dividing    */
42575697Smcpowers   while (MP_USED(rem) > MP_USED(div) || s_mp_cmp(rem, div) >= 0) {
42585697Smcpowers     int i;
42595697Smcpowers     int unusedRem;
42605697Smcpowers 
42615697Smcpowers     unusedRem = MP_USED(rem) - MP_USED(div);
42625697Smcpowers     MP_DIGITS(&part) = MP_DIGITS(rem) + unusedRem;
42635697Smcpowers     MP_ALLOC(&part)  = MP_ALLOC(rem)  - unusedRem;
42645697Smcpowers     MP_USED(&part)   = MP_USED(div);
42655697Smcpowers     if (s_mp_cmp(&part, div) < 0) {
42665697Smcpowers       -- unusedRem;
42675697Smcpowers #if MP_ARGCHK == 2
42685697Smcpowers       assert(unusedRem >= 0);
42695697Smcpowers #endif
42705697Smcpowers       -- MP_DIGITS(&part);
42715697Smcpowers       ++ MP_USED(&part);
42725697Smcpowers       ++ MP_ALLOC(&part);
42735697Smcpowers     }
42745697Smcpowers 
42755697Smcpowers     /* Compute a guess for the next quotient digit       */
42765697Smcpowers     q_msd = MP_DIGIT(&part, MP_USED(&part) - 1);
42775697Smcpowers     div_msd = MP_DIGIT(div, MP_USED(div) - 1);
42785697Smcpowers     if (q_msd >= div_msd) {
42795697Smcpowers       q_msd = 1;
42805697Smcpowers     } else if (MP_USED(&part) > 1) {
42815697Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
42825697Smcpowers       q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2);
42835697Smcpowers       q_msd /= div_msd;
42845697Smcpowers       if (q_msd == RADIX)
42855697Smcpowers         --q_msd;
42865697Smcpowers #else
42875697Smcpowers       mp_digit r;
42885697Smcpowers       MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2),
42895697Smcpowers 				  div_msd, &q_msd, &r) );
42905697Smcpowers #endif
42915697Smcpowers     } else {
42925697Smcpowers       q_msd = 0;
42935697Smcpowers     }
42945697Smcpowers #if MP_ARGCHK == 2
42955697Smcpowers     assert(q_msd > 0); /* This case should never occur any more. */
42965697Smcpowers #endif
42975697Smcpowers     if (q_msd <= 0)
42985697Smcpowers       break;
42995697Smcpowers 
43005697Smcpowers     /* See what that multiplies out to                   */
43015697Smcpowers     mp_copy(div, &t);
43025697Smcpowers     MP_CHECKOK( s_mp_mul_d(&t, (mp_digit)q_msd) );
43035697Smcpowers 
43045697Smcpowers     /*
43055697Smcpowers        If it's too big, back it off.  We should not have to do this
43065697Smcpowers        more than once, or, in rare cases, twice.  Knuth describes a
43075697Smcpowers        method by which this could be reduced to a maximum of once, but
43085697Smcpowers        I didn't implement that here.
43095697Smcpowers      * When using s_mpv_div_2dx1d, we may have to do this 3 times.
43105697Smcpowers      */
43115697Smcpowers     for (i = 4; s_mp_cmp(&t, &part) > 0 && i > 0; --i) {
43125697Smcpowers       --q_msd;
43135697Smcpowers       s_mp_sub(&t, div);	/* t -= div */
43145697Smcpowers     }
43155697Smcpowers     if (i < 0) {
43165697Smcpowers       res = MP_RANGE;
43175697Smcpowers       goto CLEANUP;
43185697Smcpowers     }
43195697Smcpowers 
43205697Smcpowers     /* At this point, q_msd should be the right next digit   */
43215697Smcpowers     MP_CHECKOK( s_mp_sub(&part, &t) );	/* part -= t */
43225697Smcpowers     s_mp_clamp(rem);
43235697Smcpowers 
43245697Smcpowers     /*
43255697Smcpowers       Include the digit in the quotient.  We allocated enough memory
43265697Smcpowers       for any quotient we could ever possibly get, so we should not
43275697Smcpowers       have to check for failures here
43285697Smcpowers      */
43295697Smcpowers     MP_DIGIT(quot, unusedRem) = (mp_digit)q_msd;
43305697Smcpowers   }
43315697Smcpowers 
43325697Smcpowers   /* Denormalize remainder                */
43335697Smcpowers   if (d) {
43345697Smcpowers     s_mp_div_2d(rem, d);
43355697Smcpowers   }
43365697Smcpowers 
43375697Smcpowers   s_mp_clamp(quot);
43385697Smcpowers 
43395697Smcpowers CLEANUP:
43405697Smcpowers   mp_clear(&t);
43415697Smcpowers 
43425697Smcpowers   return res;
43435697Smcpowers 
43445697Smcpowers } /* end s_mp_div() */
43455697Smcpowers 
43465697Smcpowers 
43475697Smcpowers /* }}} */
43485697Smcpowers 
43495697Smcpowers /* {{{ s_mp_2expt(a, k) */
43505697Smcpowers 
s_mp_2expt(mp_int * a,mp_digit k)43515697Smcpowers mp_err   s_mp_2expt(mp_int *a, mp_digit k)
43525697Smcpowers {
43535697Smcpowers   mp_err    res;
43545697Smcpowers   mp_size   dig, bit;
43555697Smcpowers 
43565697Smcpowers   dig = k / DIGIT_BIT;
43575697Smcpowers   bit = k % DIGIT_BIT;
43585697Smcpowers 
43595697Smcpowers   mp_zero(a);
43605697Smcpowers   if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
43615697Smcpowers     return res;
43625697Smcpowers 
43635697Smcpowers   DIGIT(a, dig) |= ((mp_digit)1 << bit);
43645697Smcpowers 
43655697Smcpowers   return MP_OKAY;
43665697Smcpowers 
43675697Smcpowers } /* end s_mp_2expt() */
43685697Smcpowers 
43695697Smcpowers /* }}} */
43705697Smcpowers 
43715697Smcpowers /* {{{ s_mp_reduce(x, m, mu) */
43725697Smcpowers 
43735697Smcpowers /*
43745697Smcpowers   Compute Barrett reduction, x (mod m), given a precomputed value for
43755697Smcpowers   mu = b^2k / m, where b = RADIX and k = #digits(m).  This should be
43765697Smcpowers   faster than straight division, when many reductions by the same
43775697Smcpowers   value of m are required (such as in modular exponentiation).  This
43785697Smcpowers   can nearly halve the time required to do modular exponentiation,
43795697Smcpowers   as compared to using the full integer divide to reduce.
43805697Smcpowers 
43815697Smcpowers   This algorithm was derived from the _Handbook of Applied
43825697Smcpowers   Cryptography_ by Menezes, Oorschot and VanStone, Ch. 14,
43835697Smcpowers   pp. 603-604.
43845697Smcpowers  */
43855697Smcpowers 
s_mp_reduce(mp_int * x,const mp_int * m,const mp_int * mu)43865697Smcpowers mp_err   s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu)
43875697Smcpowers {
43885697Smcpowers   mp_int   q;
43895697Smcpowers   mp_err   res;
43905697Smcpowers 
43915697Smcpowers   if((res = mp_init_copy(&q, x)) != MP_OKAY)
43925697Smcpowers     return res;
43935697Smcpowers 
43945697Smcpowers   s_mp_rshd(&q, USED(m) - 1);  /* q1 = x / b^(k-1)  */
43955697Smcpowers   s_mp_mul(&q, mu);            /* q2 = q1 * mu      */
43965697Smcpowers   s_mp_rshd(&q, USED(m) + 1);  /* q3 = q2 / b^(k+1) */
43975697Smcpowers 
43985697Smcpowers   /* x = x mod b^(k+1), quick (no division) */
43995697Smcpowers   s_mp_mod_2d(x, DIGIT_BIT * (USED(m) + 1));
44005697Smcpowers 
44015697Smcpowers   /* q = q * m mod b^(k+1), quick (no division) */
44025697Smcpowers   s_mp_mul(&q, m);
44035697Smcpowers   s_mp_mod_2d(&q, DIGIT_BIT * (USED(m) + 1));
44045697Smcpowers 
44055697Smcpowers   /* x = x - q */
44065697Smcpowers   if((res = mp_sub(x, &q, x)) != MP_OKAY)
44075697Smcpowers     goto CLEANUP;
44085697Smcpowers 
44095697Smcpowers   /* If x < 0, add b^(k+1) to it */
44105697Smcpowers   if(mp_cmp_z(x) < 0) {
44115697Smcpowers     mp_set(&q, 1);
44125697Smcpowers     if((res = s_mp_lshd(&q, USED(m) + 1)) != MP_OKAY)
44135697Smcpowers       goto CLEANUP;
44145697Smcpowers     if((res = mp_add(x, &q, x)) != MP_OKAY)
44155697Smcpowers       goto CLEANUP;
44165697Smcpowers   }
44175697Smcpowers 
44185697Smcpowers   /* Back off if it's too big */
44195697Smcpowers   while(mp_cmp(x, m) >= 0) {
44205697Smcpowers     if((res = s_mp_sub(x, m)) != MP_OKAY)
44215697Smcpowers       break;
44225697Smcpowers   }
44235697Smcpowers 
44245697Smcpowers  CLEANUP:
44255697Smcpowers   mp_clear(&q);
44265697Smcpowers 
44275697Smcpowers   return res;
44285697Smcpowers 
44295697Smcpowers } /* end s_mp_reduce() */
44305697Smcpowers 
44315697Smcpowers /* }}} */
44325697Smcpowers 
44335697Smcpowers /* }}} */
44345697Smcpowers 
44355697Smcpowers /* {{{ Primitive comparisons */
44365697Smcpowers 
44375697Smcpowers /* {{{ s_mp_cmp(a, b) */
44385697Smcpowers 
44395697Smcpowers /* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b           */
s_mp_cmp(const mp_int * a,const mp_int * b)44405697Smcpowers int      s_mp_cmp(const mp_int *a, const mp_int *b)
44415697Smcpowers {
44425697Smcpowers   mp_size used_a = MP_USED(a);
44435697Smcpowers   {
44445697Smcpowers     mp_size used_b = MP_USED(b);
44455697Smcpowers 
44465697Smcpowers     if (used_a > used_b)
44475697Smcpowers       goto IS_GT;
44485697Smcpowers     if (used_a < used_b)
44495697Smcpowers       goto IS_LT;
44505697Smcpowers   }
44515697Smcpowers   {
44525697Smcpowers     mp_digit *pa, *pb;
44535697Smcpowers     mp_digit da = 0, db = 0;
44545697Smcpowers 
44555697Smcpowers #define CMP_AB(n) if ((da = pa[n]) != (db = pb[n])) goto done
44565697Smcpowers 
44575697Smcpowers     pa = MP_DIGITS(a) + used_a;
44585697Smcpowers     pb = MP_DIGITS(b) + used_a;
44595697Smcpowers     while (used_a >= 4) {
44605697Smcpowers       pa     -= 4;
44615697Smcpowers       pb     -= 4;
44625697Smcpowers       used_a -= 4;
44635697Smcpowers       CMP_AB(3);
44645697Smcpowers       CMP_AB(2);
44655697Smcpowers       CMP_AB(1);
44665697Smcpowers       CMP_AB(0);
44675697Smcpowers     }
44685697Smcpowers     while (used_a-- > 0 && ((da = *--pa) == (db = *--pb)))
44695697Smcpowers       /* do nothing */;
44705697Smcpowers done:
44715697Smcpowers     if (da > db)
44725697Smcpowers       goto IS_GT;
44735697Smcpowers     if (da < db)
44745697Smcpowers       goto IS_LT;
44755697Smcpowers   }
44765697Smcpowers   return MP_EQ;
44775697Smcpowers IS_LT:
44785697Smcpowers   return MP_LT;
44795697Smcpowers IS_GT:
44805697Smcpowers   return MP_GT;
44815697Smcpowers } /* end s_mp_cmp() */
44825697Smcpowers 
44835697Smcpowers /* }}} */
44845697Smcpowers 
44855697Smcpowers /* {{{ s_mp_cmp_d(a, d) */
44865697Smcpowers 
44875697Smcpowers /* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d             */
s_mp_cmp_d(const mp_int * a,mp_digit d)44885697Smcpowers int      s_mp_cmp_d(const mp_int *a, mp_digit d)
44895697Smcpowers {
44905697Smcpowers   if(USED(a) > 1)
44915697Smcpowers     return MP_GT;
44925697Smcpowers 
44935697Smcpowers   if(DIGIT(a, 0) < d)
44945697Smcpowers     return MP_LT;
44955697Smcpowers   else if(DIGIT(a, 0) > d)
44965697Smcpowers     return MP_GT;
44975697Smcpowers   else
44985697Smcpowers     return MP_EQ;
44995697Smcpowers 
45005697Smcpowers } /* end s_mp_cmp_d() */
45015697Smcpowers 
45025697Smcpowers /* }}} */
45035697Smcpowers 
45045697Smcpowers /* {{{ s_mp_ispow2(v) */
45055697Smcpowers 
45065697Smcpowers /*
45075697Smcpowers   Returns -1 if the value is not a power of two; otherwise, it returns
45085697Smcpowers   k such that v = 2^k, i.e. lg(v).
45095697Smcpowers  */
s_mp_ispow2(const mp_int * v)45105697Smcpowers int      s_mp_ispow2(const mp_int *v)
45115697Smcpowers {
45125697Smcpowers   mp_digit d;
45135697Smcpowers   int      extra = 0, ix;
45145697Smcpowers 
45155697Smcpowers   ix = MP_USED(v) - 1;
45165697Smcpowers   d = MP_DIGIT(v, ix); /* most significant digit of v */
45175697Smcpowers 
45185697Smcpowers   extra = s_mp_ispow2d(d);
45195697Smcpowers   if (extra < 0 || ix == 0)
45205697Smcpowers     return extra;
45215697Smcpowers 
45225697Smcpowers   while (--ix >= 0) {
45235697Smcpowers     if (DIGIT(v, ix) != 0)
45245697Smcpowers       return -1; /* not a power of two */
45255697Smcpowers     extra += MP_DIGIT_BIT;
45265697Smcpowers   }
45275697Smcpowers 
45285697Smcpowers   return extra;
45295697Smcpowers 
45305697Smcpowers } /* end s_mp_ispow2() */
45315697Smcpowers 
45325697Smcpowers /* }}} */
45335697Smcpowers 
45345697Smcpowers /* {{{ s_mp_ispow2d(d) */
45355697Smcpowers 
s_mp_ispow2d(mp_digit d)45365697Smcpowers int      s_mp_ispow2d(mp_digit d)
45375697Smcpowers {
45385697Smcpowers   if ((d != 0) && ((d & (d-1)) == 0)) { /* d is a power of 2 */
45395697Smcpowers     int pow = 0;
45405697Smcpowers #if defined (MP_USE_UINT_DIGIT)
45415697Smcpowers     if (d & 0xffff0000U)
45425697Smcpowers       pow += 16;
45435697Smcpowers     if (d & 0xff00ff00U)
45445697Smcpowers       pow += 8;
45455697Smcpowers     if (d & 0xf0f0f0f0U)
45465697Smcpowers       pow += 4;
45475697Smcpowers     if (d & 0xccccccccU)
45485697Smcpowers       pow += 2;
45495697Smcpowers     if (d & 0xaaaaaaaaU)
45505697Smcpowers       pow += 1;
45515697Smcpowers #elif defined(MP_USE_LONG_LONG_DIGIT)
45525697Smcpowers     if (d & 0xffffffff00000000ULL)
45535697Smcpowers       pow += 32;
45545697Smcpowers     if (d & 0xffff0000ffff0000ULL)
45555697Smcpowers       pow += 16;
45565697Smcpowers     if (d & 0xff00ff00ff00ff00ULL)
45575697Smcpowers       pow += 8;
45585697Smcpowers     if (d & 0xf0f0f0f0f0f0f0f0ULL)
45595697Smcpowers       pow += 4;
45605697Smcpowers     if (d & 0xccccccccccccccccULL)
45615697Smcpowers       pow += 2;
45625697Smcpowers     if (d & 0xaaaaaaaaaaaaaaaaULL)
45635697Smcpowers       pow += 1;
45645697Smcpowers #elif defined(MP_USE_LONG_DIGIT)
45655697Smcpowers     if (d & 0xffffffff00000000UL)
45665697Smcpowers       pow += 32;
45675697Smcpowers     if (d & 0xffff0000ffff0000UL)
45685697Smcpowers       pow += 16;
45695697Smcpowers     if (d & 0xff00ff00ff00ff00UL)
45705697Smcpowers       pow += 8;
45715697Smcpowers     if (d & 0xf0f0f0f0f0f0f0f0UL)
45725697Smcpowers       pow += 4;
45735697Smcpowers     if (d & 0xccccccccccccccccUL)
45745697Smcpowers       pow += 2;
45755697Smcpowers     if (d & 0xaaaaaaaaaaaaaaaaUL)
45765697Smcpowers       pow += 1;
45775697Smcpowers #else
45785697Smcpowers #error "unknown type for mp_digit"
45795697Smcpowers #endif
45805697Smcpowers     return pow;
45815697Smcpowers   }
45825697Smcpowers   return -1;
45835697Smcpowers 
45845697Smcpowers } /* end s_mp_ispow2d() */
45855697Smcpowers 
45865697Smcpowers /* }}} */
45875697Smcpowers 
45885697Smcpowers /* }}} */
45895697Smcpowers 
45905697Smcpowers /* {{{ Primitive I/O helpers */
45915697Smcpowers 
45925697Smcpowers /* {{{ s_mp_tovalue(ch, r) */
45935697Smcpowers 
45945697Smcpowers /*
45955697Smcpowers   Convert the given character to its digit value, in the given radix.
45965697Smcpowers   If the given character is not understood in the given radix, -1 is
45975697Smcpowers   returned.  Otherwise the digit's numeric value is returned.
45985697Smcpowers 
45995697Smcpowers   The results will be odd if you use a radix < 2 or > 62, you are
46005697Smcpowers   expected to know what you're up to.
46015697Smcpowers  */
s_mp_tovalue(char ch,int r)46025697Smcpowers int      s_mp_tovalue(char ch, int r)
46035697Smcpowers {
46045697Smcpowers   int    val, xch;
46055697Smcpowers 
46065697Smcpowers   if(r > 36)
46075697Smcpowers     xch = ch;
46085697Smcpowers   else
46095697Smcpowers     xch = toupper(ch);
46105697Smcpowers 
46115697Smcpowers   if(isdigit(xch))
46125697Smcpowers     val = xch - '0';
46135697Smcpowers   else if(isupper(xch))
46145697Smcpowers     val = xch - 'A' + 10;
46155697Smcpowers   else if(islower(xch))
46165697Smcpowers     val = xch - 'a' + 36;
46175697Smcpowers   else if(xch == '+')
46185697Smcpowers     val = 62;
46195697Smcpowers   else if(xch == '/')
46205697Smcpowers     val = 63;
46215697Smcpowers   else
46225697Smcpowers     return -1;
46235697Smcpowers 
46245697Smcpowers   if(val < 0 || val >= r)
46255697Smcpowers     return -1;
46265697Smcpowers 
46275697Smcpowers   return val;
46285697Smcpowers 
46295697Smcpowers } /* end s_mp_tovalue() */
46305697Smcpowers 
46315697Smcpowers /* }}} */
46325697Smcpowers 
46335697Smcpowers /* {{{ s_mp_todigit(val, r, low) */
46345697Smcpowers 
46355697Smcpowers /*
46365697Smcpowers   Convert val to a radix-r digit, if possible.  If val is out of range
46375697Smcpowers   for r, returns zero.  Otherwise, returns an ASCII character denoting
46385697Smcpowers   the value in the given radix.
46395697Smcpowers 
46405697Smcpowers   The results may be odd if you use a radix < 2 or > 64, you are
46415697Smcpowers   expected to know what you're doing.
46425697Smcpowers  */
46435697Smcpowers 
s_mp_todigit(mp_digit val,int r,int low)46445697Smcpowers char     s_mp_todigit(mp_digit val, int r, int low)
46455697Smcpowers {
46465697Smcpowers   char   ch;
46475697Smcpowers 
46485697Smcpowers   if(val >= r)
46495697Smcpowers     return 0;
46505697Smcpowers 
46515697Smcpowers   ch = s_dmap_1[val];
46525697Smcpowers 
46535697Smcpowers   if(r <= 36 && low)
46545697Smcpowers     ch = tolower(ch);
46555697Smcpowers 
46565697Smcpowers   return ch;
46575697Smcpowers 
46585697Smcpowers } /* end s_mp_todigit() */
46595697Smcpowers 
46605697Smcpowers /* }}} */
46615697Smcpowers 
46625697Smcpowers /* {{{ s_mp_outlen(bits, radix) */
46635697Smcpowers 
46645697Smcpowers /*
46655697Smcpowers    Return an estimate for how long a string is needed to hold a radix
46665697Smcpowers    r representation of a number with 'bits' significant bits, plus an
46675697Smcpowers    extra for a zero terminator (assuming C style strings here)
46685697Smcpowers  */
s_mp_outlen(int bits,int r)46695697Smcpowers int      s_mp_outlen(int bits, int r)
46705697Smcpowers {
46715697Smcpowers   return (int)((double)bits * LOG_V_2(r) + 1.5) + 1;
46725697Smcpowers 
46735697Smcpowers } /* end s_mp_outlen() */
46745697Smcpowers 
46755697Smcpowers /* }}} */
46765697Smcpowers 
46775697Smcpowers /* }}} */
46785697Smcpowers 
46795697Smcpowers /* {{{ mp_read_unsigned_octets(mp, str, len) */
46805697Smcpowers /* mp_read_unsigned_octets(mp, str, len)
46815697Smcpowers    Read in a raw value (base 256) into the given mp_int
46825697Smcpowers    No sign bit, number is positive.  Leading zeros ignored.
46835697Smcpowers  */
46845697Smcpowers 
46855697Smcpowers mp_err
mp_read_unsigned_octets(mp_int * mp,const unsigned char * str,mp_size len)46865697Smcpowers mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len)
46875697Smcpowers {
46885697Smcpowers   int            count;
46895697Smcpowers   mp_err         res;
46905697Smcpowers   mp_digit       d;
46915697Smcpowers 
46925697Smcpowers   ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
46935697Smcpowers 
46945697Smcpowers   mp_zero(mp);
46955697Smcpowers 
46965697Smcpowers   count = len % sizeof(mp_digit);
46975697Smcpowers   if (count) {
46985697Smcpowers     for (d = 0; count-- > 0; --len) {
46995697Smcpowers       d = (d << 8) | *str++;
47005697Smcpowers     }
47015697Smcpowers     MP_DIGIT(mp, 0) = d;
47025697Smcpowers   }
47035697Smcpowers 
47045697Smcpowers   /* Read the rest of the digits */
47055697Smcpowers   for(; len > 0; len -= sizeof(mp_digit)) {
47065697Smcpowers     for (d = 0, count = sizeof(mp_digit); count > 0; --count) {
47075697Smcpowers       d = (d << 8) | *str++;
47085697Smcpowers     }
47095697Smcpowers     if (MP_EQ == mp_cmp_z(mp)) {
47105697Smcpowers       if (!d)
47115697Smcpowers 	continue;
47125697Smcpowers     } else {
47135697Smcpowers       if((res = s_mp_lshd(mp, 1)) != MP_OKAY)
47145697Smcpowers 	return res;
47155697Smcpowers     }
47165697Smcpowers     MP_DIGIT(mp, 0) = d;
47175697Smcpowers   }
47185697Smcpowers   return MP_OKAY;
47195697Smcpowers } /* end mp_read_unsigned_octets() */
47205697Smcpowers /* }}} */
47215697Smcpowers 
47225697Smcpowers /* {{{ mp_unsigned_octet_size(mp) */
47235697Smcpowers int
mp_unsigned_octet_size(const mp_int * mp)47245697Smcpowers mp_unsigned_octet_size(const mp_int *mp)
47255697Smcpowers {
47265697Smcpowers   int  bytes;
47275697Smcpowers   int  ix;
47285697Smcpowers   mp_digit  d = 0;
47295697Smcpowers 
47305697Smcpowers   ARGCHK(mp != NULL, MP_BADARG);
47315697Smcpowers   ARGCHK(MP_ZPOS == SIGN(mp), MP_BADARG);
47325697Smcpowers 
47335697Smcpowers   bytes = (USED(mp) * sizeof(mp_digit));
47345697Smcpowers 
47355697Smcpowers   /* subtract leading zeros. */
47365697Smcpowers   /* Iterate over each digit... */
47375697Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
47385697Smcpowers     d = DIGIT(mp, ix);
47395697Smcpowers     if (d)
47405697Smcpowers 	break;
47415697Smcpowers     bytes -= sizeof(d);
47425697Smcpowers   }
47435697Smcpowers   if (!bytes)
47445697Smcpowers     return 1;
47455697Smcpowers 
47465697Smcpowers   /* Have MSD, check digit bytes, high order first */
47475697Smcpowers   for(ix = sizeof(mp_digit) - 1; ix >= 0; ix--) {
47485697Smcpowers     unsigned char x = (unsigned char)(d >> (ix * CHAR_BIT));
47495697Smcpowers     if (x)
47505697Smcpowers 	break;
47515697Smcpowers     --bytes;
47525697Smcpowers   }
47535697Smcpowers   return bytes;
47545697Smcpowers } /* end mp_unsigned_octet_size() */
47555697Smcpowers /* }}} */
47565697Smcpowers 
47575697Smcpowers /* {{{ mp_to_unsigned_octets(mp, str) */
47585697Smcpowers /* output a buffer of big endian octets no longer than specified. */
47595697Smcpowers mp_err
mp_to_unsigned_octets(const mp_int * mp,unsigned char * str,mp_size maxlen)47605697Smcpowers mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
47615697Smcpowers {
47625697Smcpowers   int  ix, pos = 0;
47635697Smcpowers   int  bytes;
47645697Smcpowers 
47655697Smcpowers   ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
47665697Smcpowers 
47675697Smcpowers   bytes = mp_unsigned_octet_size(mp);
47685697Smcpowers   ARGCHK(bytes <= maxlen, MP_BADARG);
47695697Smcpowers 
47705697Smcpowers   /* Iterate over each digit... */
47715697Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
47725697Smcpowers     mp_digit  d = DIGIT(mp, ix);
47735697Smcpowers     int       jx;
47745697Smcpowers 
47755697Smcpowers     /* Unpack digit bytes, high order first */
47765697Smcpowers     for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
47775697Smcpowers       unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
47785697Smcpowers       if (!pos && !x)	/* suppress leading zeros */
47795697Smcpowers 	continue;
47805697Smcpowers       str[pos++] = x;
47815697Smcpowers     }
47825697Smcpowers   }
47835697Smcpowers   if (!pos)
47845697Smcpowers     str[pos++] = 0;
47855697Smcpowers   return pos;
47865697Smcpowers } /* end mp_to_unsigned_octets() */
47875697Smcpowers /* }}} */
47885697Smcpowers 
47895697Smcpowers /* {{{ mp_to_signed_octets(mp, str) */
47905697Smcpowers /* output a buffer of big endian octets no longer than specified. */
47915697Smcpowers mp_err
mp_to_signed_octets(const mp_int * mp,unsigned char * str,mp_size maxlen)47925697Smcpowers mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
47935697Smcpowers {
47945697Smcpowers   int  ix, pos = 0;
47955697Smcpowers   int  bytes;
47965697Smcpowers 
47975697Smcpowers   ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
47985697Smcpowers 
47995697Smcpowers   bytes = mp_unsigned_octet_size(mp);
48005697Smcpowers   ARGCHK(bytes <= maxlen, MP_BADARG);
48015697Smcpowers 
48025697Smcpowers   /* Iterate over each digit... */
48035697Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
48045697Smcpowers     mp_digit  d = DIGIT(mp, ix);
48055697Smcpowers     int       jx;
48065697Smcpowers 
48075697Smcpowers     /* Unpack digit bytes, high order first */
48085697Smcpowers     for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
48095697Smcpowers       unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
48105697Smcpowers       if (!pos) {
48115697Smcpowers 	if (!x)		/* suppress leading zeros */
48125697Smcpowers 	  continue;
48135697Smcpowers 	if (x & 0x80) { /* add one leading zero to make output positive.  */
48145697Smcpowers 	  ARGCHK(bytes + 1 <= maxlen, MP_BADARG);
48155697Smcpowers 	  if (bytes + 1 > maxlen)
48165697Smcpowers 	    return MP_BADARG;
48175697Smcpowers 	  str[pos++] = 0;
48185697Smcpowers 	}
48195697Smcpowers       }
48205697Smcpowers       str[pos++] = x;
48215697Smcpowers     }
48225697Smcpowers   }
48235697Smcpowers   if (!pos)
48245697Smcpowers     str[pos++] = 0;
48255697Smcpowers   return pos;
48265697Smcpowers } /* end mp_to_signed_octets() */
48275697Smcpowers /* }}} */
48285697Smcpowers 
48295697Smcpowers /* {{{ mp_to_fixlen_octets(mp, str) */
48305697Smcpowers /* output a buffer of big endian octets exactly as long as requested. */
48315697Smcpowers mp_err
mp_to_fixlen_octets(const mp_int * mp,unsigned char * str,mp_size length)48325697Smcpowers mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length)
48335697Smcpowers {
48345697Smcpowers   int  ix, pos = 0;
48355697Smcpowers   int  bytes;
48365697Smcpowers 
48375697Smcpowers   ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
48385697Smcpowers 
48395697Smcpowers   bytes = mp_unsigned_octet_size(mp);
48405697Smcpowers   ARGCHK(bytes <= length, MP_BADARG);
48415697Smcpowers 
48425697Smcpowers   /* place any needed leading zeros */
48435697Smcpowers   for (;length > bytes; --length) {
48445697Smcpowers 	*str++ = 0;
48455697Smcpowers   }
48465697Smcpowers 
48475697Smcpowers   /* Iterate over each digit... */
48485697Smcpowers   for(ix = USED(mp) - 1; ix >= 0; ix--) {
48495697Smcpowers     mp_digit  d = DIGIT(mp, ix);
48505697Smcpowers     int       jx;
48515697Smcpowers 
48525697Smcpowers     /* Unpack digit bytes, high order first */
48535697Smcpowers     for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
48545697Smcpowers       unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
48555697Smcpowers       if (!pos && !x)	/* suppress leading zeros */
48565697Smcpowers 	continue;
48575697Smcpowers       str[pos++] = x;
48585697Smcpowers     }
48595697Smcpowers   }
48605697Smcpowers   if (!pos)
48615697Smcpowers     str[pos++] = 0;
48625697Smcpowers   return MP_OKAY;
48635697Smcpowers } /* end mp_to_fixlen_octets() */
48645697Smcpowers /* }}} */
48655697Smcpowers 
48665697Smcpowers 
48675697Smcpowers /*------------------------------------------------------------------------*/
48685697Smcpowers /* HERE THERE BE DRAGONS                                                  */
4869*13066SDina.Nimeh@Sun.COM /* END CSTYLED */
4870