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 1055697Smcpowers mp_size mp_get_prec(void) 1065697Smcpowers { 1075697Smcpowers return s_mp_defprec; 1085697Smcpowers 1095697Smcpowers } /* end mp_get_prec() */ 1105697Smcpowers 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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; */ 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 */ 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 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 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 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 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 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 */ 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 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 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 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 */ 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 */ 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 */ 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 */ 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. */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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) */ 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 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 */ 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 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 */ 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 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 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(") = 0; 34145697Smcpowers /* Make room for the quotient */ 34155697Smcpowers MP_CHECKOK( mp_init_size(", 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(", 1); 34295697Smcpowers DIGIT(", 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(", 0) = d; 34425697Smcpowers MP_CHECKOK( s_mp_norm(&rem, ", &norm) ); 34435697Smcpowers if (norm) 34445697Smcpowers d <<= norm; 34455697Smcpowers MP_DIGIT(", 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(", 1) ); 34625697Smcpowers DIGIT(", 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("); 34775697Smcpowers mp_exch(", mp); 34785697Smcpowers CLEANUP: 34795697Smcpowers mp_clear("); 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| */ 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 */ 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) ) */ 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| */ 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 */ 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| */ 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 */ 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 */ 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 */ 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. */ 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 */ 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 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 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 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 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 */ 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 */ 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 */ 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 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 */ 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 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 */ 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 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 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 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 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 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