Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mpi.c Source File

mpi.c

Go to the documentation of this file.
00001 /**
00002  * @file mpi.c
00003  * @brief MPI (Multiple Precision Integer Arithmetic)
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneCrypto Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include "crypto.h"
00036 #include "mpi.h"
00037 #include "debug.h"
00038 
00039 //Check crypto library configuration
00040 #if (MPI_SUPPORT == ENABLED)
00041 
00042 
00043 /**
00044  * @brief Initialize a multiple precision integer
00045  * @param[in,out] r Pointer to the multiple precision integer to be initialized
00046  **/
00047 
00048 void mpiInit(Mpi *r)
00049 {
00050    //Initialize structure
00051    r->sign = 1;
00052    r->size = 0;
00053    r->data = NULL;
00054 }
00055 
00056 
00057 /**
00058  * @brief Release a multiple precision integer
00059  * @param[in,out] r Pointer to the multiple precision integer to be freed
00060  **/
00061 
00062 void mpiFree(Mpi *r)
00063 {
00064    //Any memory previously allocated?
00065    if(r->data != NULL)
00066    {
00067       //Erase contents before releasing memory
00068       memset(r->data, 0, r->size * MPI_INT_SIZE);
00069       cryptoFreeMem(r->data);
00070    }
00071 
00072    //Set size to zero
00073    r->size = 0;
00074    r->data = NULL;
00075 }
00076 
00077 
00078 /**
00079  * @brief Adjust the size of multiple precision integer
00080  * @param[in,out] r A multiple precision integer whose size is to be increased
00081  * @param[in] size Desired size in words
00082  * @return Error code
00083  **/
00084 
00085 error_t mpiGrow(Mpi *r, uint_t size)
00086 {
00087    uint_t *data;
00088 
00089    //Ensure the parameter is valid
00090    size = MAX(size, 1);
00091 
00092    //Check the current size
00093    if(r->size >= size)
00094       return NO_ERROR;
00095 
00096    //Allocate a memory buffer
00097    data = cryptoAllocMem(size * MPI_INT_SIZE);
00098    //Failed to allocate memory?
00099    if(data == NULL)
00100       return ERROR_OUT_OF_MEMORY;
00101 
00102    //Clear buffer contents
00103    memset(data, 0, size * MPI_INT_SIZE);
00104 
00105    //Any data to copy?
00106    if(r->size > 0)
00107    {
00108       //Copy original data
00109       memcpy(data, r->data, r->size * MPI_INT_SIZE);
00110       //Free previously allocated memory
00111       cryptoFreeMem(r->data);
00112    }
00113 
00114    //Update the size of the multiple precision integer
00115    r->size = size;
00116    r->data = data;
00117 
00118    //Successful operation
00119    return NO_ERROR;
00120 }
00121 
00122 
00123 /**
00124  * @brief Get the actual length in words
00125  * @param[in] a Pointer to a multiple precision integer
00126  * @return The actual length in words
00127  **/
00128 
00129 uint_t mpiGetLength(const Mpi *a)
00130 {
00131    int_t i;
00132 
00133    //Check whether the specified multiple precision integer is empty
00134    if(a->size == 0)
00135       return 0;
00136 
00137    //Start from the most significant word
00138    for(i = a->size - 1; i >= 0; i--)
00139    {
00140       //Loop as long as the current word is zero
00141       if(a->data[i] != 0)
00142          break;
00143    }
00144 
00145    //Return the actual length
00146    return i + 1;
00147 }
00148 
00149 
00150 /**
00151  * @brief Get the actual length in bytes
00152  * @param[in] a Pointer to a multiple precision integer
00153  * @return The actual byte count
00154  **/
00155 
00156 uint_t mpiGetByteLength(const Mpi *a)
00157 {
00158    uint_t n;
00159    uint32_t m;
00160 
00161    //Check whether the specified multiple precision integer is empty
00162    if(a->size == 0)
00163       return 0;
00164 
00165    //Start from the most significant word
00166    for(n = a->size - 1; n > 0; n--)
00167    {
00168       //Loop as long as the current word is zero
00169       if(a->data[n] != 0)
00170          break;
00171    }
00172 
00173    //Get the current word
00174    m = a->data[n];
00175    //Convert the length to a byte count
00176    n *= MPI_INT_SIZE;
00177 
00178    //Adjust the byte count
00179    for(; m != 0; m >>= 8) n++;
00180 
00181    //Return the actual length in bytes
00182    return n;
00183 }
00184 
00185 
00186 /**
00187  * @brief Get the actual length in bits
00188  * @param[in] a Pointer to a multiple precision integer
00189  * @return The actual bit count
00190  **/
00191 
00192 uint_t mpiGetBitLength(const Mpi *a)
00193 {
00194    uint_t n;
00195    uint32_t m;
00196 
00197    //Check whether the specified multiple precision integer is empty
00198    if(a->size == 0)
00199       return 0;
00200 
00201    //Start from the most significant word
00202    for(n = a->size - 1; n > 0; n--)
00203    {
00204       //Loop as long as the current word is zero
00205       if(a->data[n] != 0)
00206          break;
00207    }
00208 
00209    //Get the current word
00210    m = a->data[n];
00211    //Convert the length to a bit count
00212    n *= MPI_INT_SIZE * 8;
00213 
00214    //Adjust the bit count
00215    for(; m != 0; m >>= 1) n++;
00216 
00217    //Return the actual length in bits
00218    return n;
00219 }
00220 
00221 
00222 /**
00223  * @brief Set the bit value at the specified index
00224  * @param[in] r Pointer to a multiple precision integer
00225  * @param[in] index Position of the bit to be written
00226  * @param[in] value Bit value
00227  * @return Error code
00228  **/
00229 
00230 error_t mpiSetBitValue(Mpi *r, uint_t index, uint_t value)
00231 {
00232    error_t error;
00233    uint_t n1;
00234    uint_t n2;
00235 
00236    //Retrieve the position of the bit to be written
00237    n1 = index / (MPI_INT_SIZE * 8);
00238    n2 = index % (MPI_INT_SIZE * 8);
00239 
00240    //Ajust the size of the multiple precision integer if necessary
00241    error = mpiGrow(r, (index + (MPI_INT_SIZE * 8) - 1) / (MPI_INT_SIZE * 8));
00242    //Failed to adjust the size?
00243    if(error)
00244       return error;
00245 
00246    //Set bit value
00247    if(value)
00248       r->data[n1] |= (1 << n2);
00249    else
00250       r->data[n1] &= ~(1 << n2);
00251 
00252    //No error to report
00253    return NO_ERROR;
00254 }
00255 
00256 
00257 /**
00258  * @brief Get the bit value at the specified index
00259  * @param[in] a Pointer to a multiple precision integer
00260  * @param[in] index Position where to read the bit
00261  * @return The actual bit value
00262  **/
00263 
00264 uint_t mpiGetBitValue(const Mpi *a, uint_t index)
00265 {
00266    uint_t n1;
00267    uint_t n2;
00268 
00269    //Retrieve the position of the bit to be read
00270    n1 = index / (MPI_INT_SIZE * 8);
00271    n2 = index % (MPI_INT_SIZE * 8);
00272 
00273    //Index out of range?
00274    if(n1 >= a->size)
00275       return 0;
00276 
00277    //Return the actual bit value
00278    return (a->data[n1] >> n2) & 0x01;
00279 }
00280 
00281 
00282 /**
00283  * @brief Compare two multiple precision integers
00284  * @param[in] a The first multiple precision integer to be compared
00285  * @param[in] b The second multiple precision integer to be compared
00286  * @return Comparison result
00287  **/
00288 
00289 int_t mpiComp(const Mpi *a, const Mpi *b)
00290 {
00291    uint_t m;
00292    uint_t n;
00293 
00294    //Determine the actual length of A and B
00295    m = mpiGetLength(a);
00296    n = mpiGetLength(b);
00297 
00298    //Compare lengths
00299    if(!m && !n)
00300       return 0;
00301    else if(m > n)
00302       return a->sign;
00303    else if(m < n)
00304       return -b->sign;
00305 
00306    //Compare signs
00307    if(a->sign > 0 && b->sign < 0)
00308       return 1;
00309    else if(a->sign < 0 && b->sign > 0)
00310       return -1;
00311 
00312    //Then compare values
00313    while(n--)
00314    {
00315       if(a->data[n] > b->data[n])
00316          return a->sign;
00317       else if(a->data[n] < b->data[n])
00318          return -a->sign;
00319    }
00320 
00321    //Multiple precision integers are equals
00322    return 0;
00323 }
00324 
00325 
00326 /**
00327  * @brief Compare a multiple precision integer with an integer
00328  * @param[in] a Multiple precision integer to be compared
00329  * @param[in] b Integer to be compared
00330  * @return Comparison result
00331  **/
00332 
00333 int_t mpiCompInt(const Mpi *a, int_t b)
00334 {
00335    uint_t value;
00336    Mpi t;
00337 
00338    //Initialize a temporary multiple precision integer
00339    value = (b >= 0) ? b : -b;
00340    t.sign = (b >= 0) ? 1 : -1;
00341    t.size = 1;
00342    t.data = &value;
00343 
00344    //Return comparison result
00345    return mpiComp(a, &t);
00346 }
00347 
00348 
00349 /**
00350  * @brief Compare the absolute value of two multiple precision integers
00351  * @param[in] a The first multiple precision integer to be compared
00352  * @param[in] b The second multiple precision integer to be compared
00353  * @return Comparison result
00354  **/
00355 
00356 int_t mpiCompAbs(const Mpi *a, const Mpi *b)
00357 {
00358    uint_t m;
00359    uint_t n;
00360 
00361    //Determine the actual length of A and B
00362    m = mpiGetLength(a);
00363    n = mpiGetLength(b);
00364 
00365    //Compare lengths
00366    if(!m && !n)
00367       return 0;
00368    else if(m > n)
00369       return 1;
00370    else if(m < n)
00371       return -1;
00372 
00373    //Then compare values
00374    while(n--)
00375    {
00376       if(a->data[n] > b->data[n])
00377          return 1;
00378       else if(a->data[n] < b->data[n])
00379          return -1;
00380    }
00381 
00382    //Operands are equals
00383    return 0;
00384 }
00385 
00386 
00387 /**
00388  * @brief Copy a multiple precision integer
00389  * @param[out] r Pointer to a multiple precision integer (destination)
00390  * @param[in] a Pointer to a multiple precision integer (source)
00391  * @return Error code
00392  **/
00393 
00394 error_t mpiCopy(Mpi *r, const Mpi *a)
00395 {
00396    error_t error;
00397    uint_t n;
00398 
00399    //R and A are the same instance?
00400    if(r == a)
00401       return NO_ERROR;
00402 
00403    //Determine the actual length of A
00404    n = mpiGetLength(a);
00405 
00406    //Ajust the size of the destination operand
00407    error = mpiGrow(r, n);
00408    //Any error to report?
00409    if(error)
00410       return error;
00411 
00412    //Clear the contents of the multiple precision integer
00413    memset(r->data, 0, r->size * MPI_INT_SIZE);
00414    //Let R = A
00415    memcpy(r->data, a->data, n * MPI_INT_SIZE);
00416    //Set the sign of R
00417    r->sign = a->sign;
00418 
00419    //Successful operation
00420    return NO_ERROR;
00421 }
00422 
00423 
00424 /**
00425  * @brief Set the value of a multiple precision integer
00426  * @param[out] r Pointer to a multiple precision integer
00427  * @param[in] a Value to be assigned to the multiple precision integer
00428  * @return Error code
00429  **/
00430 
00431 error_t mpiSetValue(Mpi *r, int_t a)
00432 {
00433    error_t error;
00434 
00435    //Ajust the size of the destination operand
00436    error = mpiGrow(r, 1);
00437    //Failed to adjust the size?
00438    if(error)
00439       return error;
00440 
00441    //Clear the contents of the multiple precision integer
00442    memset(r->data, 0, r->size * MPI_INT_SIZE);
00443    //Set the value or R
00444    r->data[0] = (a >= 0) ? a : -a;
00445    //Set the sign of R
00446    r->sign = (a >= 0) ? 1 : -1;
00447 
00448    //Successful operation
00449    return NO_ERROR;
00450 }
00451 
00452 
00453 /**
00454  * @brief Generate a random value
00455  * @param[out] r Pointer to a multiple precision integer
00456  * @param[in] length Desired length in bits
00457  * @param[in] prngAlgo PRNG algorithm
00458  * @param[in] prngContext Pointer to the PRNG context
00459  * @return Error code
00460  **/
00461 
00462 error_t mpiRand(Mpi *r, uint_t length, const PrngAlgo *prngAlgo, void *prngContext)
00463 {
00464    error_t error;
00465    uint_t m;
00466    uint_t n;
00467 
00468    //Compute the required length, in words
00469    n = (length + (MPI_INT_SIZE * 8) - 1) / (MPI_INT_SIZE * 8);
00470    //Number of bits in the most significant word
00471    m = length % (MPI_INT_SIZE * 8);
00472 
00473    //Ajust the size of the multiple precision integer if necessary
00474    error = mpiGrow(r, n);
00475    //Failed to adjust the size?
00476    if(error)
00477       return error;
00478 
00479    //Clear the contents of the multiple precision integer
00480    memset(r->data, 0, r->size * MPI_INT_SIZE);
00481    //Set the sign of R
00482    r->sign = 1;
00483 
00484    //Generate a random pattern
00485    error = prngAlgo->read(prngContext, (uint8_t *) r->data, n * MPI_INT_SIZE);
00486    //Any error to report?
00487    if(error)
00488       return error;
00489 
00490    //Remove the meaningless bits in the most significant word
00491    if(n > 0 && m > 0)
00492       r->data[n - 1] &= (1 << m) - 1;
00493 
00494    //Successful operation
00495    return NO_ERROR;
00496 }
00497 
00498 
00499 /**
00500  * @brief Octet string to integer conversion
00501  *
00502  * Converts an octet string to a non-negative integer
00503  *
00504  * @param[out] r Non-negative integer resulting from the conversion
00505  * @param[in] data Octet string to be converted
00506  * @param[in] length Length of the octet string
00507  * @return Error code
00508  **/
00509 
00510 error_t mpiReadRaw(Mpi *r, const uint8_t *data, uint_t length)
00511 {
00512    error_t error;
00513    uint_t i;
00514 
00515    //Skip leading zeroes
00516    while(length > 1 && *data == 0)
00517    {
00518       //Advance read pointer
00519       data++;
00520       length--;
00521    }
00522 
00523    //Ajust the size of the multiple precision integer
00524    error = mpiGrow(r, (length + MPI_INT_SIZE - 1) / MPI_INT_SIZE);
00525    //Failed to adjust the size?
00526    if(error)
00527       return error;
00528 
00529    //Clear the contents of the multiple precision integer
00530    memset(r->data, 0, r->size * MPI_INT_SIZE);
00531    //Set sign
00532    r->sign = 1;
00533 
00534    //Start from the least significant byte
00535    data += length - 1;
00536 
00537    //Copy data
00538    for(i = 0; i < length; i++, data--)
00539       r->data[i / MPI_INT_SIZE] |= *data << ((i % MPI_INT_SIZE) * 8);
00540 
00541    //The conversion succeeded
00542    return NO_ERROR;
00543 }
00544 
00545 
00546 /**
00547  * @brief Integer to octet string conversion
00548  *
00549  * Converts an integer to an octet string of a specified length
00550  *
00551  * @param[in] a Non-negative integer to be converted
00552  * @param[out] data Octet string resulting from the conversion
00553  * @param[in] length Intended length of the resulting octet string
00554  * @return Error code
00555  **/
00556 
00557 error_t mpiWriteRaw(const Mpi *a, uint8_t *data, uint_t length)
00558 {
00559    uint_t i;
00560 
00561    //Get the actual length in bytes
00562    uint_t n = mpiGetByteLength(a);
00563 
00564    //Make sure the output buffer is large enough
00565    if(n > length)
00566       return ERROR_INVALID_LENGTH;
00567 
00568    //Clear output buffer
00569    memset(data, 0, length);
00570 
00571    //Start from the least significant word
00572    data += length - 1;
00573 
00574    //Copy data
00575    for(i = 0; i < n; i++, data--)
00576       *data = a->data[i / MPI_INT_SIZE] >> ((i % MPI_INT_SIZE) * 8);
00577 
00578    //The conversion succeeded
00579    return NO_ERROR;
00580 }
00581 
00582 
00583 /**
00584  * @brief Multiple precision addition
00585  * @param[out] r Resulting integer R = A + B
00586  * @param[in] a First operand A
00587  * @param[in] b Second operand B
00588  * @return Error code
00589  **/
00590 
00591 error_t mpiAdd(Mpi *r, const Mpi *a, const Mpi *b)
00592 {
00593    error_t error;
00594    int_t sign;
00595 
00596    //Retrieve the sign of A
00597    sign = a->sign;
00598 
00599    //Both operands have the same sign?
00600    if(a->sign == b->sign)
00601    {
00602       //Perform addition
00603       error = mpiAddAbs(r, a, b);
00604       //Set the sign of the resulting number
00605       r->sign = sign;
00606    }
00607    //Operands have different signs?
00608    else
00609    {
00610       //Compare the absolute value of A and B
00611       if(mpiCompAbs(a, b) >= 0)
00612       {
00613          //Perform subtraction
00614          error = mpiSubAbs(r, a, b);
00615          //Set the sign of the resulting number
00616          r->sign = sign;
00617       }
00618       else
00619       {
00620          //Perform subtraction
00621          error = mpiSubAbs(r, b, a);
00622          //Set the sign of the resulting number
00623          r->sign = -sign;
00624       }
00625    }
00626 
00627    //Return status code
00628    return error;
00629 }
00630 
00631 
00632 /**
00633  * @brief Add an integer to a multiple precision integer
00634  * @param[out] r Resulting integer R = A + B
00635  * @param[in] a First operand A
00636  * @param[in] b Second operand B
00637  * @return Error code
00638  **/
00639 
00640 error_t mpiAddInt(Mpi *r, const Mpi *a, int_t b)
00641 {
00642    uint_t value;
00643    Mpi t;
00644 
00645    //Convert the second operand to a multiple precision integer
00646    value = (b >= 0) ? b : -b;
00647    t.sign = (b >= 0) ? 1 : -1;
00648    t.size = 1;
00649    t.data = &value;
00650 
00651    //Perform addition
00652    return mpiAdd(r, a ,&t);
00653 }
00654 
00655 
00656 /**
00657  * @brief Multiple precision subtraction
00658  * @param[out] r Resulting integer R = A - B
00659  * @param[in] a First operand A
00660  * @param[in] b Second operand B
00661  * @return Error code
00662  **/
00663 
00664 error_t mpiSub(Mpi *r, const Mpi *a, const Mpi *b)
00665 {
00666    error_t error;
00667    int_t sign;
00668 
00669    //Retrieve the sign of A
00670    sign = a->sign;
00671 
00672    //Both operands have the same sign?
00673    if(a->sign == b->sign)
00674    {
00675       //Compare the absolute value of A and B
00676       if(mpiCompAbs(a, b) >= 0)
00677       {
00678          //Perform subtraction
00679          error = mpiSubAbs(r, a, b);
00680          //Set the sign of the resulting number
00681          r->sign = sign;
00682       }
00683       else
00684       {
00685          //Perform subtraction
00686          error = mpiSubAbs(r, b, a);
00687          //Set the sign of the resulting number
00688          r->sign = -sign;
00689       }
00690    }
00691    //Operands have different signs?
00692    else
00693    {
00694       //Perform addition
00695       error = mpiAddAbs(r, a, b);
00696       //Set the sign of the resulting number
00697       r->sign = sign;
00698    }
00699 
00700    //Return status code
00701    return error;
00702 }
00703 
00704 
00705 /**
00706  * @brief Subtract an integer from a multiple precision integer
00707  * @param[out] r Resulting integer R = A - B
00708  * @param[in] a First operand A
00709  * @param[in] b Second operand B
00710  * @return Error code
00711  **/
00712 
00713 error_t mpiSubInt(Mpi *r, const Mpi *a, int_t b)
00714 {
00715    uint_t value;
00716    Mpi t;
00717 
00718    //Convert the second operand to a multiple precision integer
00719    value = (b >= 0) ? b : -b;
00720    t.sign = (b >= 0) ? 1 : -1;
00721    t.size = 1;
00722    t.data = &value;
00723 
00724    //Perform subtraction
00725    return mpiSub(r, a ,&t);
00726 }
00727 
00728 
00729 /**
00730  * @brief Helper routine for multiple precision addition
00731  * @param[out] r Resulting integer R = |A + B|
00732  * @param[in] a First operand A
00733  * @param[in] b Second operand B
00734  * @return Error code
00735  **/
00736 
00737 error_t mpiAddAbs(Mpi *r, const Mpi *a, const Mpi *b)
00738 {
00739    error_t error;
00740    uint_t i;
00741    uint_t n;
00742    uint_t c;
00743    uint_t d;
00744 
00745    //R and B are the same instance?
00746    if(r == b)
00747    {
00748       //Swap A and B
00749       const Mpi *t = a;
00750       a = b;
00751       b = t;
00752    }
00753    //R is neither A nor B?
00754    else if(r != a)
00755    {
00756       //Copy the first operand to R
00757       MPI_CHECK(mpiCopy(r, a));
00758    }
00759 
00760    //Determine the actual length of B
00761    n = mpiGetLength(b);
00762    //Extend the size of the destination register as needed
00763    MPI_CHECK(mpiGrow(r, n));
00764 
00765    //The result is always positive
00766    r->sign = 1;
00767    //Clear carry bit
00768    c = 0;
00769 
00770    //Add operands
00771    for(i = 0; i < n; i++)
00772    {
00773       //Add carry bit
00774       d = r->data[i] + c;
00775       //Update carry bit
00776       if(d != 0) c = 0;
00777       //Perform addition
00778       d += b->data[i];
00779       //Update carry bit
00780       if(d < b->data[i]) c = 1;
00781       //Save result
00782       r->data[i] = d;
00783    }
00784 
00785    //Loop as long as the carry bit is set
00786    for(i = n; c && i < r->size; i++)
00787    {
00788       //Add carry bit
00789       r->data[i] += c;
00790       //Update carry bit
00791       if(r->data[i] != 0) c = 0;
00792    }
00793 
00794    //Check the final carry bit
00795    if(c && n >= r->size)
00796    {
00797       //Extend the size of the destination register
00798       MPI_CHECK(mpiGrow(r, n + 1));
00799       //Add carry bit
00800       r->data[n] = 1;
00801    }
00802 
00803 end:
00804    //Return status code
00805    return error;
00806 }
00807 
00808 
00809 /**
00810  * @brief Helper routine for multiple precision subtraction
00811  * @param[out] r Resulting integer R = |A - B|
00812  * @param[in] a First operand A
00813  * @param[in] b Second operand B
00814  * @return Error code
00815  **/
00816 
00817 error_t mpiSubAbs(Mpi *r, const Mpi *a, const Mpi *b)
00818 {
00819    error_t error;
00820    uint_t c;
00821    uint_t d;
00822    uint_t i;
00823    uint_t m;
00824    uint_t n;
00825 
00826    //Check input parameters
00827    if(mpiCompAbs(a, b) < 0)
00828    {
00829       //Swap A and B if necessary
00830       const Mpi *t = b;
00831       a = b;
00832       b = t;
00833    }
00834 
00835    //Determine the actual length of A
00836    m = mpiGetLength(a);
00837    //Determine the actual length of B
00838    n = mpiGetLength(b);
00839 
00840    //Extend the size of the destination register as needed
00841    MPI_CHECK(mpiGrow(r, m));
00842 
00843    //The result is always positive
00844    r->sign = 1;
00845    //Clear carry bit
00846    c = 0;
00847 
00848    //Subtract operands
00849    for(i = 0; i < n; i++)
00850    {
00851       //Read first operand
00852       d = a->data[i];
00853 
00854       //Check the carry bit
00855       if(c)
00856       {
00857          //Update carry bit
00858          if(d != 0) c = 0;
00859          //Propagate carry bit
00860          d -= 1;
00861       }
00862 
00863       //Update carry bit
00864       if(d < b->data[i]) c = 1;
00865       //Perform subtraction
00866       r->data[i] = d - b->data[i];
00867    }
00868 
00869    //Loop as long as the carry bit is set
00870    for(i = n; c && i < m; i++)
00871    {
00872       //Update carry bit
00873       if(a->data[i] != 0) c = 0;
00874       //Propagate carry bit
00875       r->data[i] = a->data[i] - 1;
00876    }
00877 
00878    //R and A are not the same instance?
00879    if(r != a)
00880    {
00881       //Copy the remaining words
00882       for(; i < m; i++)
00883          r->data[i] = a->data[i];
00884 
00885       //Zero the upper part of R
00886       for(; i < r->size; i++)
00887          r->data[i] = 0;
00888    }
00889 
00890 end:
00891    //Return status code
00892    return error;
00893 }
00894 
00895 
00896 /**
00897  * @brief Left shift operation
00898  * @param[in,out] r The multiple precision integer to be shifted to the left
00899  * @param[in] n The number of bits to shift
00900  * @return Error code
00901  **/
00902 
00903 error_t mpiShiftLeft(Mpi *r, uint_t n)
00904 {
00905    error_t error;
00906    uint_t i;
00907 
00908    //Number of 32-bit words to shift
00909    uint_t n1 = n / (MPI_INT_SIZE * 8);
00910    //Number of bits to shift
00911    uint_t n2 = n % (MPI_INT_SIZE * 8);
00912 
00913    //Check parameters
00914    if(!r->size || !n)
00915       return NO_ERROR;
00916 
00917    //Increase the size of the multiple-precision number
00918    error = mpiGrow(r, r->size + (n + 31) / 32);
00919    //Check return code
00920    if(error)
00921       return error;
00922 
00923    //First, shift words
00924    if(n1 > 0)
00925    {
00926       //Process the most significant words
00927       for(i = r->size - 1; i >= n1; i--)
00928          r->data[i] = r->data[i - n1];
00929       //Fill the rest with zeroes
00930       for(i = 0; i < n1; i++)
00931          r->data[i] = 0;
00932    }
00933    //Then shift bits
00934    if(n2 > 0)
00935    {
00936       //Process the most significant words
00937       for(i = r->size - 1; i >= 1; i--)
00938          r->data[i] = (r->data[i] << n2) | (r->data[i - 1] >> (32 - n2));
00939       //The least significant word requires a special handling
00940       r->data[0] <<= n2;
00941    }
00942 
00943    //Shift operation is complete
00944    return NO_ERROR;
00945 }
00946 
00947 
00948 /**
00949  * @brief Right shift operation
00950  * @param[in,out] r The multiple precision integer to be shifted to the right
00951  * @param[in] n The number of bits to shift
00952  * @return Error code
00953  **/
00954 
00955 error_t mpiShiftRight(Mpi *r, uint_t n)
00956 {
00957    uint_t i;
00958    uint_t m;
00959 
00960    //Number of 32-bit words to shift
00961    uint_t n1 = n / (MPI_INT_SIZE * 8);
00962    //Number of bits to shift
00963    uint_t n2 = n % (MPI_INT_SIZE * 8);
00964 
00965    //Check parameters
00966    if(n1 >= r->size)
00967    {
00968       memset(r->data, 0, r->size * MPI_INT_SIZE);
00969       return NO_ERROR;
00970    }
00971 
00972    //First, shift words
00973    if(n1 > 0)
00974    {
00975       //Process the least significant words
00976       for(m = r->size - n1, i = 0; i < m; i++)
00977          r->data[i] = r->data[i + n1];
00978       //Fill the rest with zeroes
00979       for(i = m; i < r->size; i++)
00980          r->data[i] = 0;
00981    }
00982    //Then shift bits
00983    if(n2 > 0)
00984    {
00985       //Process the least significant words
00986       for(m = r->size - n1 - 1, i = 0; i < m; i++)
00987          r->data[i] = (r->data[i] >> n2) | (r->data[i + 1] << (32 - n2));
00988       //The most significant word requires a special handling
00989       r->data[m] >>= n2;
00990    }
00991 
00992    //Shift operation is complete
00993    return NO_ERROR;
00994 }
00995 
00996 
00997 /**
00998  * @brief Multiple precision multiplication
00999  * @param[out] r Resulting integer R = A * B
01000  * @param[in] a First operand A
01001  * @param[in] b Second operand B
01002  * @return Error code
01003  **/
01004 
01005 error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
01006 {
01007    error_t error;
01008    int_t i;
01009    int_t m;
01010    int_t n;
01011    Mpi ta;
01012    Mpi tb;
01013 
01014    //Initialize multiple precision integers
01015    mpiInit(&ta);
01016    mpiInit(&tb);
01017 
01018    //R and A are the same instance?
01019    if(r == a)
01020    {
01021       //Copy A to TA
01022       MPI_CHECK(mpiCopy(&ta, a));
01023       //Use TA instead of A
01024       a = &ta;
01025    }
01026 
01027    //R and B are the same instance?
01028    if(r == b)
01029    {
01030       //Copy B to TB
01031       MPI_CHECK(mpiCopy(&tb, b));
01032       //Use TB instead of B
01033       b = &tb;
01034    }
01035 
01036    //Determine the actual length of A and B
01037    m = mpiGetLength(a);
01038    n = mpiGetLength(b);
01039 
01040    //Adjust the size of R
01041    MPI_CHECK(mpiGrow(r, m + n));
01042    //Set the sign of R
01043    r->sign = (a->sign == b->sign) ? 1 : -1;
01044 
01045    //Clear the contents of the destination integer
01046    memset(r->data, 0, r->size * MPI_INT_SIZE);
01047 
01048    //Perform multiplication
01049    if(m < n)
01050    {
01051       for(i = 0; i < m; i++)
01052          mpiMulAccCore(&r->data[i], b->data, n, a->data[i]);
01053    }
01054    else
01055    {
01056       for(i = 0; i < n; i++)
01057          mpiMulAccCore(&r->data[i], a->data, m, b->data[i]);
01058    }
01059 
01060 end:
01061    //Release multiple precision integers
01062    mpiFree(&ta);
01063    mpiFree(&tb);
01064 
01065    //Return status code
01066    return error;
01067 }
01068 
01069 
01070 /**
01071  * @brief Multiply a multiple precision integer by an integer
01072  * @param[out] r Resulting integer R = A * B
01073  * @param[in] a First operand A
01074  * @param[in] b Second operand B
01075  * @return Error code
01076  **/
01077 
01078 error_t mpiMulInt(Mpi *r, const Mpi *a, int_t b)
01079 {
01080    uint_t value;
01081    Mpi t;
01082 
01083    //Convert the second operand to a multiple precision integer
01084    value = (b >= 0) ? b : -b;
01085    t.sign = (b >= 0) ? 1 : -1;
01086    t.size = 1;
01087    t.data = &value;
01088 
01089    //Perform multiplication
01090    return mpiMul(r, a, &t);
01091 }
01092 
01093 
01094 /**
01095  * @brief Multiple precision division
01096  * @param[out] q The quotient Q = A / B
01097  * @param[out] r The remainder R = A mod B
01098  * @param[in] a The dividend A
01099  * @param[in] b The divisor B
01100  * @return Error code
01101  **/
01102 
01103 error_t mpiDiv(Mpi *q, Mpi *r, const Mpi *a, const Mpi *b)
01104 {
01105    error_t error;
01106    uint_t m;
01107    uint_t n;
01108    Mpi c;
01109    Mpi d;
01110    Mpi e;
01111 
01112    //Check whether the divisor is equal to zero
01113    if(!mpiCompInt(b, 0))
01114       return ERROR_INVALID_PARAMETER;
01115 
01116    //Initialize multiple precision integers
01117    mpiInit(&c);
01118    mpiInit(&d);
01119    mpiInit(&e);
01120 
01121    MPI_CHECK(mpiCopy(&c, a));
01122    MPI_CHECK(mpiCopy(&d, b));
01123    MPI_CHECK(mpiSetValue(&e, 0));
01124 
01125    m = mpiGetBitLength(&c);
01126    n = mpiGetBitLength(&d);
01127 
01128    if(m > n)
01129       MPI_CHECK(mpiShiftLeft(&d, m - n));
01130 
01131    while(n++ <= m)
01132    {
01133       MPI_CHECK(mpiShiftLeft(&e, 1));
01134 
01135       if(mpiComp(&c, &d) >= 0)
01136       {
01137          MPI_CHECK(mpiSetBitValue(&e, 0, 1));
01138          MPI_CHECK(mpiSub(&c, &c, &d));
01139       }
01140 
01141       MPI_CHECK(mpiShiftRight(&d, 1));
01142    }
01143 
01144    if(q != NULL)
01145       MPI_CHECK(mpiCopy(q, &e));
01146 
01147    if(r != NULL)
01148       MPI_CHECK(mpiCopy(r, &c));
01149 
01150 end:
01151    //Release previously allocated memory
01152    mpiFree(&c);
01153    mpiFree(&d);
01154    mpiFree(&e);
01155 
01156    //Return status code
01157    return error;
01158 }
01159 
01160 
01161 /**
01162  * @brief Divide a multiple precision integer by an integer
01163  * @param[out] q The quotient Q = A / B
01164  * @param[out] r The remainder R = A mod B
01165  * @param[in] a The dividend A
01166  * @param[in] b The divisor B
01167  * @return Error code
01168  **/
01169 
01170 error_t mpiDivInt(Mpi *q, Mpi *r, const Mpi *a, int_t b)
01171 {
01172    uint_t value;
01173    Mpi t;
01174 
01175    //Convert the divisor to a multiple precision integer
01176    value = (b >= 0) ? b : -b;
01177    t.sign = (b >= 0) ? 1 : -1;
01178    t.size = 1;
01179    t.data = &value;
01180 
01181    //Perform division
01182    return mpiDiv(q, r, a, &t);
01183 }
01184 
01185 
01186 /**
01187  * @brief Modulo operation
01188  * @param[out] r Resulting integer R = A mod P
01189  * @param[in] a The multiple precision integer to be reduced
01190  * @param[in] p The modulus P
01191  * @return Error code
01192  **/
01193 
01194 error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
01195 {
01196    error_t error;
01197    int_t sign;
01198    uint_t m;
01199    uint_t n;
01200    Mpi c;
01201 
01202    //Make sure the modulus is positive
01203    if(mpiCompInt(p, 0) <= 0)
01204       return ERROR_INVALID_PARAMETER;
01205 
01206    //Initialize multiple precision integer
01207    mpiInit(&c);
01208 
01209    //Save the sign of A
01210    sign = a->sign;
01211    //Determine the actual length of A
01212    m = mpiGetBitLength(a);
01213    //Determine the actual length of P
01214    n = mpiGetBitLength(p);
01215 
01216    //Let R = A
01217    MPI_CHECK(mpiCopy(r, a));
01218 
01219    if(m >= n)
01220    {
01221       MPI_CHECK(mpiCopy(&c, p));
01222       MPI_CHECK(mpiShiftLeft(&c, m - n));
01223 
01224       while(mpiCompAbs(r, p) >= 0)
01225       {
01226          if(mpiCompAbs(r, &c) >= 0)
01227          {
01228             MPI_CHECK(mpiSubAbs(r, r, &c));
01229          }
01230 
01231          MPI_CHECK(mpiShiftRight(&c, 1));
01232       }
01233    }
01234 
01235    if(sign < 0)
01236    {
01237       MPI_CHECK(mpiSubAbs(r, p, r));
01238    }
01239 
01240 end:
01241    //Release previously allocated memory
01242    mpiFree(&c);
01243 
01244    //Return status code
01245    return error;
01246 }
01247 
01248 
01249 
01250 /**
01251  * @brief Modular addition
01252  * @param[out] r Resulting integer R = A + B mod P
01253  * @param[in] a The first operand A
01254  * @param[in] b The second operand B
01255  * @param[in] p The modulus P
01256  * @return Error code
01257  **/
01258 
01259 error_t mpiAddMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
01260 {
01261    error_t error;
01262 
01263    //Perform modular addition
01264    MPI_CHECK(mpiAdd(r, a, b));
01265    MPI_CHECK(mpiMod(r, r, p));
01266 
01267 end:
01268    //Return status code
01269    return error;
01270 }
01271 
01272 
01273 /**
01274  * @brief Modular subtraction
01275  * @param[out] r Resulting integer R = A - B mod P
01276  * @param[in] a The first operand A
01277  * @param[in] b The second operand B
01278  * @param[in] p The modulus P
01279  * @return Error code
01280  **/
01281 
01282 error_t mpiSubMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
01283 {
01284    error_t error;
01285 
01286    //Perform modular subtraction
01287    MPI_CHECK(mpiSub(r, a, b));
01288    MPI_CHECK(mpiMod(r, r, p));
01289 
01290 end:
01291    //Return status code
01292    return error;
01293 }
01294 
01295 
01296 /**
01297  * @brief Modular multiplication
01298  * @param[out] r Resulting integer R = A * B mod P
01299  * @param[in] a The first operand A
01300  * @param[in] b The second operand B
01301  * @param[in] p The modulus P
01302  * @return Error code
01303  **/
01304 
01305 error_t mpiMulMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
01306 {
01307    error_t error;
01308 
01309    //Perform modular multiplication
01310    MPI_CHECK(mpiMul(r, a, b));
01311    MPI_CHECK(mpiMod(r, r, p));
01312 
01313 end:
01314    //Return status code
01315    return error;
01316 }
01317 
01318 
01319 /**
01320  * @brief Modular inverse
01321  * @param[out] r Resulting integer R = A^-1 mod P
01322  * @param[in] a The multiple precision integer A
01323  * @param[in] p The modulus P
01324  * @return Error code
01325  **/
01326 
01327 error_t mpiInvMod(Mpi *r, const Mpi *a, const Mpi *p)
01328 {
01329    error_t error;
01330    Mpi b;
01331    Mpi c;
01332    Mpi q0;
01333    Mpi r0;
01334    Mpi t;
01335    Mpi u;
01336    Mpi v;
01337 
01338    //Initialize multiple precision integers
01339    mpiInit(&b);
01340    mpiInit(&c);
01341    mpiInit(&q0);
01342    mpiInit(&r0);
01343    mpiInit(&t);
01344    mpiInit(&u);
01345    mpiInit(&v);
01346 
01347    MPI_CHECK(mpiCopy(&b, p));
01348    MPI_CHECK(mpiCopy(&c, a));
01349    MPI_CHECK(mpiSetValue(&u, 0));
01350    MPI_CHECK(mpiSetValue(&v, 1));
01351 
01352    while(mpiCompInt(&c, 0) > 0)
01353    {
01354       MPI_CHECK(mpiDiv(&q0, &r0, &b, &c));
01355 
01356       MPI_CHECK(mpiCopy(&b, &c));
01357       MPI_CHECK(mpiCopy(&c, &r0));
01358 
01359       MPI_CHECK(mpiCopy(&t, &v));
01360       MPI_CHECK(mpiMul(&q0, &q0, &v));
01361       MPI_CHECK(mpiSub(&v, &u, &q0));
01362       MPI_CHECK(mpiCopy(&u, &t));
01363    }
01364 
01365    if(mpiCompInt(&b, 1))
01366    {
01367       MPI_CHECK(ERROR_FAILURE);
01368    }
01369 
01370    if(mpiCompInt(&u, 0) > 0)
01371    {
01372       MPI_CHECK(mpiCopy(r, &u));
01373    }
01374    else
01375    {
01376       MPI_CHECK(mpiAdd(r, &u, p));
01377    }
01378 
01379 end:
01380    //Release previously allocated memory
01381    mpiFree(&b);
01382    mpiFree(&c);
01383    mpiFree(&q0);
01384    mpiFree(&r0);
01385    mpiFree(&t);
01386    mpiFree(&u);
01387    mpiFree(&v);
01388 
01389    //Return status code
01390    return error;
01391 }
01392 
01393 
01394 /**
01395  * @brief Modular exponentiation
01396  * @param[out] r Resulting integer R = A ^ E mod P
01397  * @param[in] a Pointer to a multiple precision integer
01398  * @param[in] e Exponent
01399  * @param[in] p Modulus
01400  * @return Error code
01401  **/
01402 
01403 error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
01404 {
01405    error_t error;
01406    int_t i;
01407    int_t j;
01408    int_t n;
01409    uint_t d;
01410    uint_t k;
01411    uint_t u;
01412    Mpi b;
01413    Mpi c2;
01414    Mpi t;
01415    Mpi s[8];
01416 
01417    //Initialize multiple precision integers
01418    mpiInit(&b);
01419    mpiInit(&c2);
01420    mpiInit(&t);
01421 
01422    //Initialize precomputed values
01423    for(i = 0; i < arraysize(s); i++)
01424       mpiInit(&s[i]);
01425 
01426    //Very small exponents are often selected with low Hamming weight.
01427    //The sliding window mechanism should be disabled in that case
01428    d = (mpiGetBitLength(e) <= 32) ? 1 : 4;
01429 
01430    //Even modulus?
01431    if(mpiIsEven(p))
01432    {
01433       //Let B = A^2
01434       MPI_CHECK(mpiMulMod(&b, a, a, p));
01435       //Let S[0] = A
01436       MPI_CHECK(mpiCopy(&s[0], a));
01437 
01438       //Precompute S[i] = A^(2 * i + 1)
01439       for(i = 1; i < (1 << (d - 1)); i++)
01440       {
01441          MPI_CHECK(mpiMulMod(&s[i], &s[i - 1], &b, p));
01442       }
01443 
01444       //Let R = 1
01445       MPI_CHECK(mpiSetValue(r, 1));
01446 
01447       //The exponent is processed in a right-to-left fashion
01448       i = mpiGetBitLength(e) - 1;
01449 
01450       //Perform sliding window exponentiation
01451       while(i >= 0)
01452       {
01453          //The sliding window exponentiation algorithm decomposes E
01454          //into zero and nonzero windows
01455          if(!mpiGetBitValue(e, i))
01456          {
01457             //Compute R = R^2
01458             MPI_CHECK(mpiMulMod(r, r, r, p));
01459             //Next bit to be processed
01460             i--;
01461          }
01462          else
01463          {
01464             //Find the longest window
01465             n = MAX(i - d + 1, 0);
01466 
01467             //The least significant bit of the window must be equal to 1
01468             while(!mpiGetBitValue(e, n)) n++;
01469 
01470             //The algorithm processes more than one bit per iteration
01471             for(u = 0, j = i; j >= n; j--)
01472             {
01473                //Compute R = R^2
01474                MPI_CHECK(mpiMulMod(r, r, r, p));
01475                //Compute the relevant index to be used in the precomputed table
01476                u = (u << 1) | mpiGetBitValue(e, j);
01477             }
01478 
01479             //Perform a single multiplication per iteration
01480             MPI_CHECK(mpiMulMod(r, r, &s[u >> 1], p));
01481             //Next bit to be processed
01482             i = n - 1;
01483          }
01484       }
01485    }
01486    else
01487    {
01488       //Compute the smaller C = (2^32)^k such as C > P
01489       k = mpiGetLength(p);
01490 
01491       //Compute C^2 mod P
01492       MPI_CHECK(mpiSetValue(&c2, 1));
01493       MPI_CHECK(mpiShiftLeft(&c2, 2 * k * (MPI_INT_SIZE * 8)));
01494       MPI_CHECK(mpiMod(&c2, &c2, p));
01495 
01496       //Let B = A * C mod P
01497       if(mpiComp(a, p) >= 0)
01498       {
01499          MPI_CHECK(mpiMod(&b, a, p));
01500          MPI_CHECK(mpiMontgomeryMul(&b, &b, &c2, k, p, &t));
01501       }
01502       else
01503       {
01504          MPI_CHECK(mpiMontgomeryMul(&b, a, &c2, k, p, &t));
01505       }
01506 
01507       //Let R = B^2 * C^-1 mod P
01508       MPI_CHECK(mpiMontgomeryMul(r, &b, &b, k, p, &t));
01509       //Let S[0] = B
01510       MPI_CHECK(mpiCopy(&s[0], &b));
01511 
01512       //Precompute S[i] = B^(2 * i + 1) * C^-1 mod P
01513       for(i = 1; i < (1 << (d - 1)); i++)
01514       {
01515          MPI_CHECK(mpiMontgomeryMul(&s[i], &s[i - 1], r, k, p, &t));
01516       }
01517 
01518       //Let R = C mod P
01519       MPI_CHECK(mpiCopy(r, &c2));
01520       MPI_CHECK(mpiMontgomeryRed(r, r, k, p, &t));
01521 
01522       //The exponent is processed in a right-to-left fashion
01523       i = mpiGetBitLength(e) - 1;
01524 
01525       //Perform sliding window exponentiation
01526       while(i >= 0)
01527       {
01528          //The sliding window exponentiation algorithm decomposes E
01529          //into zero and nonzero windows
01530          if(!mpiGetBitValue(e, i))
01531          {
01532             //Compute R = R^2 * C^-1 mod P
01533             MPI_CHECK(mpiMontgomeryMul(r, r, r, k, p, &t));
01534             //Next bit to be processed
01535             i--;
01536          }
01537          else
01538          {
01539             //Find the longest window
01540             n = MAX(i - d + 1, 0);
01541 
01542             //The least significant bit of the window must be equal to 1
01543             while(!mpiGetBitValue(e, n)) n++;
01544 
01545             //The algorithm processes more than one bit per iteration
01546             for(u = 0, j = i; j >= n; j--)
01547             {
01548                //Compute R = R^2 * C^-1 mod P
01549                MPI_CHECK(mpiMontgomeryMul(r, r, r, k, p, &t));
01550                //Compute the relevant index to be used in the precomputed table
01551                u = (u << 1) | mpiGetBitValue(e, j);
01552             }
01553 
01554             //Compute R = R * T[u/2] * C^-1 mod P
01555             MPI_CHECK(mpiMontgomeryMul(r, r, &s[u >> 1], k, p, &t));
01556             //Next bit to be processed
01557             i = n - 1;
01558          }
01559       }
01560 
01561       //Compute R = R * C^-1 mod P
01562       MPI_CHECK(mpiMontgomeryRed(r, r, k, p, &t));
01563    }
01564 
01565 end:
01566    //Release multiple precision integers
01567    mpiFree(&b);
01568    mpiFree(&c2);
01569    mpiFree(&t);
01570 
01571    //Release precomputed values
01572    for(i = 0; i < arraysize(s); i++)
01573       mpiFree(&s[i]);
01574 
01575    //Return status code
01576    return error;
01577 }
01578 
01579 
01580 /**
01581  * @brief Montgomery multiplication
01582  * @param[out] r Resulting integer R = A * B / 2^k mod P
01583  * @param[in] a An integer A such as 0 <= A < 2^k
01584  * @param[in] b An integer B such as 0 <= B < 2^k
01585  * @param[in] k An integer k such as P < 2^k
01586  * @param[in] p Modulus P
01587  * @param[in] t An preallocated integer T (for internal operation)
01588  * @return Error code
01589  **/
01590 
01591 error_t mpiMontgomeryMul(Mpi *r, const Mpi *a, const Mpi *b, uint_t k, const Mpi *p, Mpi *t)
01592 {
01593    error_t error;
01594    uint_t i;
01595    uint_t m;
01596    uint_t n;
01597    uint_t q;
01598 
01599    //Use Newton's method to compute the inverse of P[0] mod 2^32
01600    for(m = 2 - p->data[0], i = 0; i < 4; i++)
01601       m = m * (2 - m * p->data[0]);
01602 
01603    //Precompute -1/P[0] mod 2^32;
01604    m = ~m + 1;
01605 
01606    //We assume that B is always less than 2^k
01607    n = MIN(b->size, k);
01608 
01609    //Make sure T is large enough
01610    MPI_CHECK(mpiGrow(t, 2 * k + 1));
01611    //Let T = 0
01612    MPI_CHECK(mpiSetValue(t, 0));
01613 
01614    //Perform Montgomery multiplication
01615    for(i = 0; i < k; i++)
01616    {
01617       //Check current index
01618       if(i < a->size)
01619       {
01620          //Compute q = ((T[i] + A[i] * B[0]) * m) mod 2^32
01621          q = (t->data[i] + a->data[i] * b->data[0]) * m;
01622          //Compute T = T + A[i] * B
01623          mpiMulAccCore(t->data + i, b->data, n, a->data[i]);
01624       }
01625       else
01626       {
01627          //Compute q = (T[i] * m) mod 2^32
01628          q = t->data[i] * m;
01629       }
01630 
01631       //Compute T = T + q * P
01632       mpiMulAccCore(t->data + i, p->data, k, q);
01633    }
01634 
01635    //Compute R = T / 2^(32 * k)
01636    MPI_CHECK(mpiShiftRight(t, k * (MPI_INT_SIZE * 8)));
01637    MPI_CHECK(mpiCopy(r, t));
01638 
01639    //A final subtraction is required
01640    if(mpiComp(r, p) >= 0)
01641    {
01642       MPI_CHECK(mpiSub(r, r, p));
01643    }
01644 
01645 end:
01646    //Return status code
01647    return error;
01648 }
01649 
01650 
01651 /**
01652  * @brief Montgomery reduction
01653  * @param[out] r Resulting integer R = A / 2^k mod P
01654  * @param[in] a An integer A such as 0 <= A < 2^k
01655  * @param[in] k An integer k such as P < 2^k
01656  * @param[in] p Modulus P
01657  * @param[in] t An preallocated integer T (for internal operation)
01658  * @return Error code
01659  **/
01660 
01661 error_t mpiMontgomeryRed(Mpi *r, const Mpi *a, uint_t k, const Mpi *p, Mpi *t)
01662 {
01663    uint_t value;
01664    Mpi b;
01665 
01666    //Let B = 1
01667    value = 1;
01668    b.sign = 1;
01669    b.size = 1;
01670    b.data = &value;
01671 
01672    //Compute R = A / 2^k mod P
01673    return mpiMontgomeryMul(r, a, &b, k, p, t);
01674 }
01675 
01676 
01677 #if (MPI_ASM_SUPPORT == DISABLED)
01678 
01679 /**
01680  * @brief Multiply-accumulate operation
01681  * @param[out] r Resulting integer
01682  * @param[in] a First operand A
01683  * @param[in] m Size of A in words
01684  * @param[in] b Second operand B
01685  **/
01686 
01687 void mpiMulAccCore(uint_t *r, const uint_t *a, int_t m, const uint_t b)
01688 {
01689    int_t i;
01690    uint32_t c;
01691    uint32_t u;
01692    uint32_t v;
01693    uint64_t p;
01694 
01695    //Clear variables
01696    c = 0;
01697    u = 0;
01698    v = 0;
01699 
01700    //Perform multiplication
01701    for(i = 0; i < m; i++)
01702    {
01703       p = (uint64_t) a[i] * b;
01704       u = (uint32_t) p;
01705       v = (uint32_t) (p >> 32);
01706 
01707       u += c;
01708       if(u < c) v++;
01709 
01710       u += r[i];
01711       if(u < r[i]) v++;
01712 
01713       r[i] = u;
01714       c = v;
01715    }
01716 
01717    //Propagate carry
01718    for(; c != 0; i++)
01719    {
01720       r[i] += c;
01721       c = (r[i] < c);
01722    }
01723 }
01724 
01725 #endif
01726 
01727 
01728 /**
01729  * @brief Display the contents of a multiple precision integer
01730  * @param[in] stream Pointer to a FILE object that identifies an output stream
01731  * @param[in] prepend String to prepend to the left of each line
01732  * @param[in] a Pointer to a multiple precision integer
01733  **/
01734 
01735 void mpiDump(FILE *stream, const char_t *prepend, const Mpi *a)
01736 {
01737    uint_t i;
01738 
01739    //Process each word
01740    for(i = 0; i < a->size; i++)
01741    {
01742       //Beginning of a new line?
01743       if(i == 0 || ((a->size - i - 1) % 8) == 7)
01744          fprintf(stream, "%s", prepend);
01745 
01746       //Display current data
01747       fprintf(stream, "%08X ", a->data[a->size - 1 - i]);
01748 
01749       //End of current line?
01750       if(!((a->size - i - 1) % 8) || i == (a->size - 1))
01751          fprintf(stream, "\r\n");
01752    }
01753 }
01754 
01755 #endif
01756