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