Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
mpi.c
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
Generated on Tue Jul 12 2022 17:10:15 by
1.7.2