mpi.c
Go to the documentation of this file.
1 /**
2  * @file mpi.c
3  * @brief MPI (Multiple Precision Integer Arithmetic)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "mpi/mpi.h"
37 #include "debug.h"
38 
39 //Check crypto library configuration
40 #if (MPI_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Initialize a multiple precision integer
45  * @param[in,out] r Pointer to the multiple precision integer to be initialized
46  **/
47 
48 void mpiInit(Mpi *r)
49 {
50  //Initialize structure
51  r->sign = 1;
52  r->size = 0;
53 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
54  r->data = NULL;
55 #endif
56 }
57 
58 
59 /**
60  * @brief Release a multiple precision integer
61  * @param[in,out] r Pointer to the multiple precision integer to be freed
62  **/
63 
64 void mpiFree(Mpi *r)
65 {
66  uint_t i;
67 
68 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
69  //Any memory previously allocated?
70  if(r->data != NULL)
71  {
72  //Erase contents
73  for(i = 0; i < r->size; i++)
74  {
75  r->data[i] = 0;
76  }
77 
78  //Release memory buffer
79  cryptoFreeMem(r->data);
80  r->data = NULL;
81  }
82 #else
83  //Erase contents
84  for(i = 0; i < r->size; i++)
85  {
86  r->data[i] = 0;
87  }
88 #endif
89 
90  //Reset size to zero
91  r->size = 0;
92 }
93 
94 
95 /**
96  * @brief Adjust the size of multiple precision integer
97  * @param[in,out] r A multiple precision integer whose size is to be increased
98  * @param[in] size Desired size in words
99  * @return Error code
100  **/
101 
103 {
104  error_t error;
105  uint_t i;
106 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
107  mpi_word_t *data;
108 #endif
109 
110  //Initialize status code
111  error = NO_ERROR;
112 
113  //Ensure the parameter is valid
114  size = MAX(size, 1);
115 
116  //Check whether the size of the multiple precision integer must be increased
117  if(size > r->size)
118  {
119 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
120  //Allocate a new memory buffer
121  data = cryptoAllocMem(size * sizeof(mpi_word_t));
122 
123  //Successful memory allocation?
124  if(data != NULL)
125  {
126  //Any data to copy?
127  if(r->size > 0)
128  {
129  //Copy original data
130  for(i = 0; i < r->size; i++)
131  {
132  data[i] = r->data[i];
133  r->data[i] = 0;
134  }
135 
136  //Release old memory buffer
137  cryptoFreeMem(r->data);
138  }
139 
140  //Clear upper words
141  for(i = r->size; i < size; i++)
142  {
143  data[i] = 0;
144  }
145 
146  //Attach new memory buffer
147  r->data = data;
148  //Update the size of the multiple precision integer
149  r->size = size;
150  }
151  else
152  {
153  //Failed to allocate memory
154  error = ERROR_OUT_OF_MEMORY;
155  }
156 #else
157  //Check parameter
158  if(size <= MPI_MAX_WORDS)
159  {
160  //Clear upper words
161  for(i = r->size; i < size; i++)
162  {
163  r->data[i] = 0;
164  }
165 
166  //Update the size of the multiple precision integer
167  r->size = size;
168  }
169  else
170  {
171  //Report an error
172  error = ERROR_BUFFER_OVERFLOW;
173  }
174 #endif
175  }
176 
177  //Return status code
178  return error;
179 }
180 
181 
182 /**
183  * @brief Get the actual length in words
184  * @param[in] a Pointer to a multiple precision integer
185  * @return The actual length in words
186  **/
187 
189 {
190  int_t i;
191 
192  //Check whether the specified multiple precision integer is empty
193  if(a->size == 0)
194  return 0;
195 
196  //Start from the most significant word
197  for(i = a->size - 1; i >= 0; i--)
198  {
199  //Loop as long as the current word is zero
200  if(a->data[i] != 0)
201  break;
202  }
203 
204  //Return the actual length
205  return i + 1;
206 }
207 
208 
209 /**
210  * @brief Get the actual length in bytes
211  * @param[in] a Pointer to a multiple precision integer
212  * @return The actual byte count
213  **/
214 
216 {
217  uint_t n;
218  uint32_t m;
219 
220  //Check whether the specified multiple precision integer is empty
221  if(a->size == 0)
222  return 0;
223 
224  //Start from the most significant word
225  for(n = a->size - 1; n > 0; n--)
226  {
227  //Loop as long as the current word is zero
228  if(a->data[n] != 0)
229  break;
230  }
231 
232  //Get the current word
233  m = a->data[n];
234  //Convert the length to a byte count
236 
237  //Adjust the byte count
238  for(; m != 0; m >>= 8)
239  {
240  n++;
241  }
242 
243  //Return the actual length in bytes
244  return n;
245 }
246 
247 
248 /**
249  * @brief Get the actual length in bits
250  * @param[in] a Pointer to a multiple precision integer
251  * @return The actual bit count
252  **/
253 
255 {
256  uint_t n;
257  uint32_t m;
258 
259  //Check whether the specified multiple precision integer is empty
260  if(a->size == 0)
261  return 0;
262 
263  //Start from the most significant word
264  for(n = a->size - 1; n > 0; n--)
265  {
266  //Loop as long as the current word is zero
267  if(a->data[n] != 0)
268  break;
269  }
270 
271  //Get the current word
272  m = a->data[n];
273  //Convert the length to a bit count
274  n *= MPI_BITS_PER_WORD;
275 
276  //Adjust the bit count
277  for(; m != 0; m >>= 1)
278  {
279  n++;
280  }
281 
282  //Return the actual length in bits
283  return n;
284 }
285 
286 
287 /**
288  * @brief Set the bit value at the specified index
289  * @param[in] r Pointer to a multiple precision integer
290  * @param[in] index Position of the bit to be written
291  * @param[in] value Bit value
292  * @return Error code
293  **/
294 
296 {
297  error_t error;
298  uint_t n1;
299  uint_t n2;
300 
301  //Retrieve the position of the bit to be written
302  n1 = index / MPI_BITS_PER_WORD;
303  n2 = index % MPI_BITS_PER_WORD;
304 
305  //Ajust the size of the multiple precision integer if necessary
306  error = mpiGrow(r, n1 + 1);
307  //Failed to adjust the size?
308  if(error)
309  return error;
310 
311  //Set bit value
312  if(value != 0)
313  {
314  r->data[n1] |= (1U << n2);
315  }
316  else
317  {
318  r->data[n1] &= ~(1U << n2);
319  }
320 
321  //Successful operation
322  return NO_ERROR;
323 }
324 
325 
326 /**
327  * @brief Get the bit value at the specified index
328  * @param[in] a Pointer to a multiple precision integer
329  * @param[in] index Position where to read the bit
330  * @return The actual bit value
331  **/
332 
334 {
335  uint_t n1;
336  uint_t n2;
337 
338  //Retrieve the position of the bit to be read
339  n1 = index / MPI_BITS_PER_WORD;
340  n2 = index % MPI_BITS_PER_WORD;
341 
342  //Index out of range?
343  if(n1 >= a->size)
344  return 0;
345 
346  //Return the actual bit value
347  return (a->data[n1] >> n2) & 0x01;
348 }
349 
350 
351 /**
352  * @brief Compare two multiple precision integers
353  * @param[in] a The first multiple precision integer to be compared
354  * @param[in] b The second multiple precision integer to be compared
355  * @return Comparison result
356  **/
357 
358 int_t mpiComp(const Mpi *a, const Mpi *b)
359 {
360  uint_t m;
361  uint_t n;
362  int_t res;
363 
364  //Initialize variable
365  res = 0;
366 
367  //Determine the actual length of A and B
368  m = mpiGetLength(a);
369  n = mpiGetLength(b);
370 
371  //Compare lengths
372  if(m == 0 && n == 0)
373  {
374  res = 0;
375  }
376  else if(m > n)
377  {
378  res = a->sign;
379  }
380  else if(m < n)
381  {
382  res = -b->sign;
383  }
384  else
385  {
386  //Compare signs
387  if(a->sign > 0 && b->sign < 0)
388  {
389  res = 1;
390  }
391  else if(a->sign < 0 && b->sign > 0)
392  {
393  res = -1;
394  }
395  else
396  {
397  //Compare values
398  while(n-- > 0)
399  {
400  if(a->data[n] > b->data[n])
401  {
402  res = a->sign;
403  break;
404  }
405  else if(a->data[n] < b->data[n])
406  {
407  res = -a->sign;
408  break;
409  }
410  else
411  {
412  }
413  }
414  }
415  }
416 
417  //Return comparison result
418  return res;
419 }
420 
421 
422 /**
423  * @brief Compare a multiple precision integer with an integer
424  * @param[in] a Multiple precision integer to be compared
425  * @param[in] b Integer to be compared
426  * @return Comparison result
427  **/
428 
430 {
432  Mpi t;
433 
434  //Initialize a temporary multiple precision integer
435  value = (b >= 0) ? b : -b;
436  t.sign = (b >= 0) ? 1 : -1;
437  t.size = 1;
438 
439 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
440  t.data = &value;
441 #else
442  t.data[0] = value;
443 #endif
444 
445  //Return comparison result
446  return mpiComp(a, &t);
447 }
448 
449 
450 /**
451  * @brief Compare the absolute value of two multiple precision integers
452  * @param[in] a The first multiple precision integer to be compared
453  * @param[in] b The second multiple precision integer to be compared
454  * @return Comparison result
455  **/
456 
457 int_t mpiCompAbs(const Mpi *a, const Mpi *b)
458 {
459  uint_t m;
460  uint_t n;
461  int_t res;
462 
463  //Initialize variable
464  res = 0;
465 
466  //Determine the actual length of A and B
467  m = mpiGetLength(a);
468  n = mpiGetLength(b);
469 
470  //Compare lengths
471  if(m == 0 && n == 0)
472  {
473  res = 0;
474  }
475  else if(m > n)
476  {
477  res = 1;
478  }
479  else if(m < n)
480  {
481  res = -1;
482  }
483  else
484  {
485  //Compare values
486  while(n-- > 0)
487  {
488  if(a->data[n] > b->data[n])
489  {
490  res = 1;
491  break;
492  }
493  else if(a->data[n] < b->data[n])
494  {
495  res = -1;
496  break;
497  }
498  else
499  {
500  }
501  }
502  }
503 
504  //Return comparison result
505  return res;
506 }
507 
508 
509 /**
510  * @brief Copy a multiple precision integer
511  * @param[out] r Pointer to a multiple precision integer (destination)
512  * @param[in] a Pointer to a multiple precision integer (source)
513  * @return Error code
514  **/
515 
517 {
518  error_t error;
519  uint_t i;
520  uint_t n;
521 
522  //R and A are the same instance?
523  if(r == a)
524  return NO_ERROR;
525 
526  //Determine the actual length of A
527  n = mpiGetLength(a);
528 
529  //Ajust the size of the destination operand
530  error = mpiGrow(r, n);
531  //Any error to report?
532  if(error)
533  return error;
534 
535  //Set the sign of R
536  r->sign = a->sign;
537 
538  //Let R = A
539  for(i = 0; i < n; i++)
540  {
541  r->data[i] = a->data[i];
542  }
543 
544  //Clear upper words
545  for(; i < r->size; i++)
546  {
547  r->data[i] = 0;
548  }
549 
550  //Successful operation
551  return NO_ERROR;
552 }
553 
554 
555 /**
556  * @brief Set the value of a multiple precision integer
557  * @param[out] r Pointer to a multiple precision integer
558  * @param[in] a Value to be assigned to the multiple precision integer
559  * @return Error code
560  **/
561 
563 {
564  error_t error;
565  uint_t i;
566 
567  //Ajust the size of the destination operand
568  error = mpiGrow(r, 1);
569  //Failed to adjust the size?
570  if(error)
571  return error;
572 
573  //Clear the contents of the multiple precision integer
574  for(i = 0; i < r->size; i++)
575  {
576  r->data[i] = 0;
577  }
578 
579  //Set the value or R
580  r->data[0] = (a >= 0) ? a : -a;
581  //Set the sign of R
582  r->sign = (a >= 0) ? 1 : -1;
583 
584  //Successful operation
585  return NO_ERROR;
586 }
587 
588 
589 /**
590  * @brief Generate a random value
591  * @param[out] r Pointer to a multiple precision integer
592  * @param[in] length Desired length in bits
593  * @param[in] prngAlgo PRNG algorithm
594  * @param[in] prngContext Pointer to the PRNG context
595  * @return Error code
596  **/
597 
598 error_t mpiRand(Mpi *r, uint_t length, const PrngAlgo *prngAlgo,
599  void *prngContext)
600 {
601  error_t error;
602  uint_t i;
603  uint_t m;
604  uint_t n;
605 
606  //Compute the required length, in words
608  //Number of bits in the most significant word
610 
611  //Ajust the size of the multiple precision integer if necessary
612  error = mpiGrow(r, n);
613  //Failed to adjust the size?
614  if(error)
615  return error;
616 
617  //Clear the contents of the multiple precision integer
618  for(i = 0; i < r->size; i++)
619  {
620  r->data[i] = 0;
621  }
622 
623  //Set the sign of R
624  r->sign = 1;
625 
626  //Generate a random pattern
627  error = prngAlgo->read(prngContext, (uint8_t *) r->data, n * sizeof(mpi_word_t));
628  //Any error to report?
629  if(error)
630  return error;
631 
632  //Remove the meaningless bits in the most significant word
633  if(n > 0 && m > 0)
634  {
635  r->data[n - 1] &= (1U << m) - 1;
636  }
637 
638  //Successful operation
639  return NO_ERROR;
640 }
641 
642 
643 /**
644  * @brief Generate a random value in the range 1 to p-1
645  * @param[out] r Pointer to a multiple precision integer
646  * @param[in] p The upper bound of the range
647  * @param[in] prngAlgo PRNG algorithm
648  * @param[in] prngContext Pointer to the PRNG context
649  * @return Error code
650  **/
651 
652 error_t mpiRandRange(Mpi *r, const Mpi *p, const PrngAlgo *prngAlgo,
653  void *prngContext)
654 {
655  error_t error;
656  uint_t n;
657  Mpi a;
658 
659  //Make sure p is greater than 1
660  if(mpiCompInt(p, 1) <= 0)
662 
663  //Initialize multiple precision integer
664  mpiInit(&a);
665 
666  //Get the actual length of p
667  n = mpiGetBitLength(p);
668 
669  //Generate extra random bits so that the bias produced by the modular
670  //reduction is negligible
671  MPI_CHECK(mpiRand(r, n + 64, prngAlgo, prngContext));
672 
673  //Compute r = (r mod (p - 1)) + 1
674  MPI_CHECK(mpiSubInt(&a, p, 1));
675  MPI_CHECK(mpiMod(r, r, &a));
676  MPI_CHECK(mpiAddInt(r, r, 1));
677 
678 end:
679  //Release previously allocated memory
680  mpiFree(&a);
681 
682  //Return status code
683  return error;
684 }
685 
686 
687 /**
688  * @brief Test whether a number is probable prime
689  * @param[in] a Pointer to a multiple precision integer
690  * @return Error code
691  **/
692 
693 __weak_func error_t mpiCheckProbablePrime(const Mpi *a)
694 {
695  //This function is a placeholder for hardware implementation
696  return ERROR_NOT_IMPLEMENTED;
697 }
698 
699 
700 /**
701  * @brief Octet string to integer conversion
702  *
703  * Converts an octet string to a non-negative integer
704  *
705  * @param[out] r Non-negative integer resulting from the conversion
706  * @param[in] input Octet string to be converted
707  * @param[in] length Length of the octet string
708  * @param[in] format Input format
709  * @return Error code
710  **/
711 
712 error_t mpiImport(Mpi *r, const uint8_t *input, size_t length,
713  MpiFormat format)
714 {
715  error_t error;
716  uint_t i;
717  mpi_word_t temp;
718 
719  //Check input format
720  if(format == MPI_FORMAT_LITTLE_ENDIAN)
721  {
722  //Skip trailing zeroes
723  while(length > 0 && input[length - 1] == 0)
724  {
725  length--;
726  }
727 
728  //Ajust the size of the multiple precision integer
730 
731  //Check status code
732  if(!error)
733  {
734  //Clear the contents of the multiple precision integer
735  for(i = 0; i < r->size; i++)
736  {
737  r->data[i] = 0;
738  }
739 
740  //Set sign
741  r->sign = 1;
742 
743  //Import data
744  for(i = 0; i < length; i++, input++)
745  {
746  temp = *input & 0xFF;
747  r->data[i / MPI_BYTES_PER_WORD] |= temp << ((i % MPI_BYTES_PER_WORD) * 8);
748  }
749  }
750  }
751  else if(format == MPI_FORMAT_BIG_ENDIAN)
752  {
753  //Skip leading zeroes
754  while(length > 1 && *input == 0)
755  {
756  input++;
757  length--;
758  }
759 
760  //Ajust the size of the multiple precision integer
762 
763  //Check status code
764  if(!error)
765  {
766  //Clear the contents of the multiple precision integer
767  for(i = 0; i < r->size; i++)
768  {
769  r->data[i] = 0;
770  }
771 
772  //Set sign
773  r->sign = 1;
774 
775  //Start from the least significant byte
776  input += length - 1;
777 
778  //Import data
779  for(i = 0; i < length; i++, input--)
780  {
781  temp = *input & 0xFF;
782  r->data[i / MPI_BYTES_PER_WORD] |= temp << ((i % MPI_BYTES_PER_WORD) * 8);
783  }
784  }
785  }
786  else
787  {
788  //Report an error
789  error = ERROR_INVALID_PARAMETER;
790  }
791 
792  //Return status code
793  return error;
794 }
795 
796 
797 /**
798  * @brief Integer to octet string conversion
799  *
800  * Converts an integer to an octet string of a specified length
801  *
802  * @param[in] a Non-negative integer to be converted
803  * @param[out] output Octet string resulting from the conversion
804  * @param[in] length Intended length of the resulting octet string
805  * @param[in] format Output format
806  * @return Error code
807  **/
808 
809 error_t mpiExport(const Mpi *a, uint8_t *output, size_t length,
810  MpiFormat format)
811 {
812  error_t error;
813  uint_t i;
814  uint_t n;
815  mpi_word_t temp;
816 
817  //Initialize status code
818  error = NO_ERROR;
819 
820  //Check input format
821  if(format == MPI_FORMAT_LITTLE_ENDIAN)
822  {
823  //Get the actual length in bytes
824  n = mpiGetByteLength(a);
825 
826  //Make sure the output buffer is large enough
827  if(n <= length)
828  {
829  //Clear output buffer
830  osMemset(output, 0, length);
831 
832  //Export data
833  for(i = 0; i < n; i++, output++)
834  {
835  temp = a->data[i / MPI_BYTES_PER_WORD] >> ((i % MPI_BYTES_PER_WORD) * 8);
836  *output = temp & 0xFF;
837  }
838  }
839  else
840  {
841  //Report an error
842  error = ERROR_INVALID_LENGTH;
843  }
844  }
845  else if(format == MPI_FORMAT_BIG_ENDIAN)
846  {
847  //Get the actual length in bytes
848  n = mpiGetByteLength(a);
849 
850  //Make sure the output buffer is large enough
851  if(n <= length)
852  {
853  //Clear output buffer
854  osMemset(output, 0, length);
855 
856  //Point to the least significant word
857  output += length - 1;
858 
859  //Export data
860  for(i = 0; i < n; i++, output--)
861  {
862  temp = a->data[i / MPI_BYTES_PER_WORD] >> ((i % MPI_BYTES_PER_WORD) * 8);
863  *output = temp & 0xFF;
864  }
865  }
866  else
867  {
868  //Report an error
869  error = ERROR_INVALID_LENGTH;
870  }
871  }
872  else
873  {
874  //Report an error
875  error = ERROR_INVALID_PARAMETER;
876  }
877 
878  //Return status code
879  return error;
880 }
881 
882 
883 /**
884  * @brief Multiple precision addition
885  * @param[out] r Resulting integer R = A + B
886  * @param[in] a First operand A
887  * @param[in] b Second operand B
888  * @return Error code
889  **/
890 
891 error_t mpiAdd(Mpi *r, const Mpi *a, const Mpi *b)
892 {
893  error_t error;
894  int_t sign;
895 
896  //Retrieve the sign of A
897  sign = a->sign;
898 
899  //Both operands have the same sign?
900  if(a->sign == b->sign)
901  {
902  //Perform addition
903  error = mpiAddAbs(r, a, b);
904  //Set the sign of the resulting number
905  r->sign = sign;
906  }
907  //Operands have different signs?
908  else
909  {
910  //Compare the absolute value of A and B
911  if(mpiCompAbs(a, b) >= 0)
912  {
913  //Perform subtraction
914  error = mpiSubAbs(r, a, b);
915  //Set the sign of the resulting number
916  r->sign = sign;
917  }
918  else
919  {
920  //Perform subtraction
921  error = mpiSubAbs(r, b, a);
922  //Set the sign of the resulting number
923  r->sign = -sign;
924  }
925  }
926 
927  //Return status code
928  return error;
929 }
930 
931 
932 /**
933  * @brief Add an integer to a multiple precision integer
934  * @param[out] r Resulting integer R = A + B
935  * @param[in] a First operand A
936  * @param[in] b Second operand B
937  * @return Error code
938  **/
939 
941 {
943  Mpi t;
944 
945  //Convert the second operand to a multiple precision integer
946  value = (b >= 0) ? b : -b;
947  t.sign = (b >= 0) ? 1 : -1;
948  t.size = 1;
949 
950 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
951  t.data = &value;
952 #else
953  t.data[0] = value;
954 #endif
955 
956  //Perform addition
957  return mpiAdd(r, a, &t);
958 }
959 
960 
961 /**
962  * @brief Multiple precision subtraction
963  * @param[out] r Resulting integer R = A - B
964  * @param[in] a First operand A
965  * @param[in] b Second operand B
966  * @return Error code
967  **/
968 
969 error_t mpiSub(Mpi *r, const Mpi *a, const Mpi *b)
970 {
971  error_t error;
972  int_t sign;
973 
974  //Retrieve the sign of A
975  sign = a->sign;
976 
977  //Both operands have the same sign?
978  if(a->sign == b->sign)
979  {
980  //Compare the absolute value of A and B
981  if(mpiCompAbs(a, b) >= 0)
982  {
983  //Perform subtraction
984  error = mpiSubAbs(r, a, b);
985  //Set the sign of the resulting number
986  r->sign = sign;
987  }
988  else
989  {
990  //Perform subtraction
991  error = mpiSubAbs(r, b, a);
992  //Set the sign of the resulting number
993  r->sign = -sign;
994  }
995  }
996  //Operands have different signs?
997  else
998  {
999  //Perform addition
1000  error = mpiAddAbs(r, a, b);
1001  //Set the sign of the resulting number
1002  r->sign = sign;
1003  }
1004 
1005  //Return status code
1006  return error;
1007 }
1008 
1009 
1010 /**
1011  * @brief Subtract an integer from a multiple precision integer
1012  * @param[out] r Resulting integer R = A - B
1013  * @param[in] a First operand A
1014  * @param[in] b Second operand B
1015  * @return Error code
1016  **/
1017 
1019 {
1020  mpi_word_t value;
1021  Mpi t;
1022 
1023  //Convert the second operand to a multiple precision integer
1024  value = (b >= 0) ? b : -b;
1025  t.sign = (b >= 0) ? 1 : -1;
1026  t.size = 1;
1027 
1028 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1029  t.data = &value;
1030 #else
1031  t.data[0] = value;
1032 #endif
1033 
1034  //Perform subtraction
1035  return mpiSub(r, a, &t);
1036 }
1037 
1038 
1039 /**
1040  * @brief Helper routine for multiple precision addition
1041  * @param[out] r Resulting integer R = |A + B|
1042  * @param[in] a First operand A
1043  * @param[in] b Second operand B
1044  * @return Error code
1045  **/
1046 
1047 error_t mpiAddAbs(Mpi *r, const Mpi *a, const Mpi *b)
1048 {
1049  error_t error;
1050  uint_t i;
1051  uint_t n;
1052  mpi_word_t c;
1053  mpi_word_t d;
1054 
1055  //R and B are the same instance?
1056  if(r == b)
1057  {
1058  //Swap A and B
1059  const Mpi *t = a;
1060  a = b;
1061  b = t;
1062  }
1063  //R is neither A nor B?
1064  else if(r != a)
1065  {
1066  //Copy the first operand to R
1067  MPI_CHECK(mpiCopy(r, a));
1068  }
1069 
1070  //Determine the actual length of B
1071  n = mpiGetLength(b);
1072  //Extend the size of the destination register as needed
1073  MPI_CHECK(mpiGrow(r, n));
1074 
1075  //The result is always positive
1076  r->sign = 1;
1077  //Clear carry bit
1078  c = 0;
1079 
1080  //Add operands
1081  for(i = 0; i < n; i++)
1082  {
1083  //Add carry bit
1084  d = r->data[i] + c;
1085 
1086  //Update carry bit
1087  if(d != 0)
1088  {
1089  c = 0;
1090  }
1091 
1092  //Perform addition
1093  d += b->data[i];
1094 
1095  //Update carry bit
1096  if(d < b->data[i])
1097  {
1098  c = 1;
1099  }
1100 
1101  //Save result
1102  r->data[i] = d;
1103  }
1104 
1105  //Loop as long as the carry bit is set
1106  for(i = n; c && i < r->size; i++)
1107  {
1108  //Add carry bit
1109  r->data[i] += c;
1110 
1111  //Update carry bit
1112  if(r->data[i] != 0)
1113  {
1114  c = 0;
1115  }
1116  }
1117 
1118  //Check the final carry bit
1119  if(c && n >= r->size)
1120  {
1121  //Extend the size of the destination register
1122  MPI_CHECK(mpiGrow(r, n + 1));
1123  //Add carry bit
1124  r->data[n] = 1;
1125  }
1126 
1127 end:
1128  //Return status code
1129  return error;
1130 }
1131 
1132 
1133 /**
1134  * @brief Helper routine for multiple precision subtraction
1135  * @param[out] r Resulting integer R = |A - B|
1136  * @param[in] a First operand A
1137  * @param[in] b Second operand B
1138  * @return Error code
1139  **/
1140 
1141 error_t mpiSubAbs(Mpi *r, const Mpi *a, const Mpi *b)
1142 {
1143  error_t error;
1144  uint_t i;
1145  uint_t m;
1146  uint_t n;
1147  mpi_word_t c;
1148  mpi_word_t d;
1149 
1150  //Check input parameters
1151  if(mpiCompAbs(a, b) < 0)
1152  {
1153  //Swap A and B if necessary
1154  const Mpi *t = a;
1155  a = b;
1156  b = t;
1157  }
1158 
1159  //Determine the actual length of A
1160  m = mpiGetLength(a);
1161  //Determine the actual length of B
1162  n = mpiGetLength(b);
1163 
1164  //Extend the size of the destination register as needed
1165  MPI_CHECK(mpiGrow(r, m));
1166 
1167  //The result is always positive
1168  r->sign = 1;
1169  //Clear carry bit
1170  c = 0;
1171 
1172  //Subtract operands
1173  for(i = 0; i < n; i++)
1174  {
1175  //Read first operand
1176  d = a->data[i];
1177 
1178  //Check the carry bit
1179  if(c != 0)
1180  {
1181  //Update carry bit
1182  if(d != 0)
1183  {
1184  c = 0;
1185  }
1186 
1187  //Propagate carry bit
1188  d -= 1;
1189  }
1190 
1191  //Update carry bit
1192  if(d < b->data[i])
1193  {
1194  c = 1;
1195  }
1196 
1197  //Perform subtraction
1198  r->data[i] = d - b->data[i];
1199  }
1200 
1201  //Loop as long as the carry bit is set
1202  for(i = n; c && i < m; i++)
1203  {
1204  //Update carry bit
1205  if(a->data[i] != 0)
1206  {
1207  c = 0;
1208  }
1209 
1210  //Propagate carry bit
1211  r->data[i] = a->data[i] - 1;
1212  }
1213 
1214  //R and A are not the same instance?
1215  if(r != a)
1216  {
1217  //Copy the remaining words
1218  for(; i < m; i++)
1219  {
1220  r->data[i] = a->data[i];
1221  }
1222 
1223  //Zero the upper part
1224  for(; i < r->size; i++)
1225  {
1226  r->data[i] = 0;
1227  }
1228  }
1229 
1230 end:
1231  //Return status code
1232  return error;
1233 }
1234 
1235 
1236 /**
1237  * @brief Left shift operation
1238  * @param[in,out] r The multiple precision integer to be shifted to the left
1239  * @param[in] n The number of bits to shift
1240  * @return Error code
1241  **/
1242 
1244 {
1245  error_t error;
1246  uint_t i;
1247  uint_t k;
1248  uint_t n1;
1249  uint_t n2;
1250 
1251  //Check parameters
1252  if(r->size == 0 || n == 0)
1253  return NO_ERROR;
1254 
1255  //Determine the actual length of r
1256  k = mpiGetBitLength(r);
1257 
1258  //Number of 32-bit words to shift
1259  n1 = n / MPI_BITS_PER_WORD;
1260  //Number of bits to shift
1261  n2 = n % MPI_BITS_PER_WORD;
1262 
1263  //Increase the size of the multiple-precision number
1264  error = mpiGrow(r, (k + n + (MPI_BITS_PER_WORD - 1)) / MPI_BITS_PER_WORD);
1265  //Check return code
1266  if(error)
1267  return error;
1268 
1269  //First, shift words
1270  if(n1 > 0)
1271  {
1272  //Process the most significant words
1273  for(i = r->size - 1; i >= n1; i--)
1274  {
1275  r->data[i] = r->data[i - n1];
1276  }
1277 
1278  //Fill the rest with zeroes
1279  for(i = 0; i < n1; i++)
1280  {
1281  r->data[i] = 0;
1282  }
1283  }
1284 
1285  //Then shift bits
1286  if(n2 > 0)
1287  {
1288  //Process the most significant words
1289  for(i = r->size - 1; i >= 1; i--)
1290  {
1291  r->data[i] = (r->data[i] << n2) | (r->data[i - 1] >> (MPI_BITS_PER_WORD - n2));
1292  }
1293 
1294  //The least significant word requires a special handling
1295  r->data[0] <<= n2;
1296  }
1297 
1298  //Shift operation is complete
1299  return NO_ERROR;
1300 }
1301 
1302 
1303 /**
1304  * @brief Right shift operation
1305  * @param[in,out] r The multiple precision integer to be shifted to the right
1306  * @param[in] n The number of bits to shift
1307  * @return Error code
1308  **/
1309 
1311 {
1312  uint_t i;
1313  uint_t m;
1314 
1315  //Number of 32-bit words to shift
1316  uint_t n1 = n / MPI_BITS_PER_WORD;
1317  //Number of bits to shift
1318  uint_t n2 = n % MPI_BITS_PER_WORD;
1319 
1320  //Check parameters
1321  if(n1 >= r->size)
1322  {
1323  //Clear the contents of the multiple precision integer
1324  for(i = 0; i < r->size; i++)
1325  {
1326  r->data[i] = 0;
1327  }
1328 
1329  //We are done
1330  return NO_ERROR;
1331  }
1332 
1333  //First, shift words
1334  if(n1 > 0)
1335  {
1336  //Process the least significant words
1337  for(m = r->size - n1, i = 0; i < m; i++)
1338  {
1339  r->data[i] = r->data[i + n1];
1340  }
1341 
1342  //Fill the rest with zeroes
1343  for(i = m; i < r->size; i++)
1344  {
1345  r->data[i] = 0;
1346  }
1347  }
1348 
1349  //Then shift bits
1350  if(n2 > 0)
1351  {
1352  //Process the least significant words
1353  for(m = r->size - n1 - 1, i = 0; i < m; i++)
1354  {
1355  r->data[i] = (r->data[i] >> n2) | (r->data[i + 1] << (MPI_BITS_PER_WORD - n2));
1356  }
1357 
1358  //The most significant word requires a special handling
1359  r->data[m] >>= n2;
1360  }
1361 
1362  //Shift operation is complete
1363  return NO_ERROR;
1364 }
1365 
1366 
1367 /**
1368  * @brief Multiple precision multiplication
1369  * @param[out] r Resulting integer R = A * B
1370  * @param[in] a First operand A
1371  * @param[in] b Second operand B
1372  * @return Error code
1373  **/
1374 
1375 __weak_func error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
1376 {
1377  error_t error;
1378  uint_t i;
1379  uint_t m;
1380  uint_t n;
1381  Mpi ta;
1382  Mpi tb;
1383 
1384  //Initialize multiple precision integers
1385  mpiInit(&ta);
1386  mpiInit(&tb);
1387 
1388  //R and A are the same instance?
1389  if(r == a)
1390  {
1391  //Copy A to TA
1392  MPI_CHECK(mpiCopy(&ta, a));
1393  //Use TA instead of A
1394  a = &ta;
1395  }
1396 
1397  //R and B are the same instance?
1398  if(r == b)
1399  {
1400  //Copy B to TB
1401  MPI_CHECK(mpiCopy(&tb, b));
1402  //Use TB instead of B
1403  b = &tb;
1404  }
1405 
1406  //Determine the actual length of A and B
1407  m = mpiGetLength(a);
1408  n = mpiGetLength(b);
1409 
1410  //Adjust the size of R
1411  MPI_CHECK(mpiGrow(r, m + n));
1412  //Set the sign of R
1413  r->sign = (a->sign == b->sign) ? 1 : -1;
1414 
1415  //Clear the contents of the destination integer
1416  for(i = 0; i < r->size; i++)
1417  {
1418  r->data[i] = 0;
1419  }
1420 
1421  //Perform multiplication
1422  if(m < n)
1423  {
1424  for(i = 0; i < m; i++)
1425  {
1426  mpiMulAccCore(&r->data[i], b->data, n, a->data[i]);
1427  }
1428  }
1429  else
1430  {
1431  for(i = 0; i < n; i++)
1432  {
1433  mpiMulAccCore(&r->data[i], a->data, m, b->data[i]);
1434  }
1435  }
1436 
1437 end:
1438  //Release multiple precision integers
1439  mpiFree(&ta);
1440  mpiFree(&tb);
1441 
1442  //Return status code
1443  return error;
1444 }
1445 
1446 
1447 /**
1448  * @brief Multiply a multiple precision integer by an integer
1449  * @param[out] r Resulting integer R = A * B
1450  * @param[in] a First operand A
1451  * @param[in] b Second operand B
1452  * @return Error code
1453  **/
1454 
1456 {
1457  mpi_word_t value;
1458  Mpi t;
1459 
1460  //Convert the second operand to a multiple precision integer
1461  value = (b >= 0) ? b : -b;
1462  t.sign = (b >= 0) ? 1 : -1;
1463  t.size = 1;
1464 
1465 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1466  t.data = &value;
1467 #else
1468  t.data[0] = value;
1469 #endif
1470 
1471  //Perform multiplication
1472  return mpiMul(r, a, &t);
1473 }
1474 
1475 
1476 /**
1477  * @brief Multiple precision division
1478  * @param[out] q The quotient Q = A / B
1479  * @param[out] r The remainder R = A mod B
1480  * @param[in] a The dividend A
1481  * @param[in] b The divisor B
1482  * @return Error code
1483  **/
1484 
1485 error_t mpiDiv(Mpi *q, Mpi *r, const Mpi *a, const Mpi *b)
1486 {
1487  error_t error;
1488  uint_t m;
1489  uint_t n;
1490  Mpi c;
1491  Mpi d;
1492  Mpi e;
1493 
1494  //Check whether the divisor is equal to zero
1495  if(!mpiCompInt(b, 0))
1496  return ERROR_INVALID_PARAMETER;
1497 
1498  //Initialize multiple precision integers
1499  mpiInit(&c);
1500  mpiInit(&d);
1501  mpiInit(&e);
1502 
1503  MPI_CHECK(mpiCopy(&c, a));
1504  MPI_CHECK(mpiCopy(&d, b));
1505  MPI_CHECK(mpiSetValue(&e, 0));
1506 
1507  m = mpiGetBitLength(&c);
1508  n = mpiGetBitLength(&d);
1509 
1510  if(m > n)
1511  {
1512  MPI_CHECK(mpiShiftLeft(&d, m - n));
1513  }
1514 
1515  while(n++ <= m)
1516  {
1517  MPI_CHECK(mpiShiftLeft(&e, 1));
1518 
1519  if(mpiComp(&c, &d) >= 0)
1520  {
1521  MPI_CHECK(mpiSetBitValue(&e, 0, 1));
1522  MPI_CHECK(mpiSub(&c, &c, &d));
1523  }
1524 
1525  MPI_CHECK(mpiShiftRight(&d, 1));
1526  }
1527 
1528  if(q != NULL)
1529  {
1530  MPI_CHECK(mpiCopy(q, &e));
1531  }
1532 
1533  if(r != NULL)
1534  {
1535  MPI_CHECK(mpiCopy(r, &c));
1536  }
1537 
1538 end:
1539  //Release previously allocated memory
1540  mpiFree(&c);
1541  mpiFree(&d);
1542  mpiFree(&e);
1543 
1544  //Return status code
1545  return error;
1546 }
1547 
1548 
1549 /**
1550  * @brief Divide a multiple precision integer by an integer
1551  * @param[out] q The quotient Q = A / B
1552  * @param[out] r The remainder R = A mod B
1553  * @param[in] a The dividend A
1554  * @param[in] b The divisor B
1555  * @return Error code
1556  **/
1557 
1559 {
1560  mpi_word_t value;
1561  Mpi t;
1562 
1563  //Convert the divisor to a multiple precision integer
1564  value = (b >= 0) ? b : -b;
1565  t.sign = (b >= 0) ? 1 : -1;
1566  t.size = 1;
1567 
1568 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1569  t.data = &value;
1570 #else
1571  t.data[0] = value;
1572 #endif
1573 
1574  //Perform division
1575  return mpiDiv(q, r, a, &t);
1576 }
1577 
1578 
1579 /**
1580  * @brief Modulo operation
1581  * @param[out] r Resulting integer R = A mod P
1582  * @param[in] a The multiple precision integer to be reduced
1583  * @param[in] p The modulus P
1584  * @return Error code
1585  **/
1586 
1587 error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
1588 {
1589  error_t error;
1590  int_t sign;
1591  uint_t m;
1592  uint_t n;
1593  Mpi c;
1594 
1595  //Make sure the modulus is positive
1596  if(mpiCompInt(p, 0) <= 0)
1597  return ERROR_INVALID_PARAMETER;
1598 
1599  //Initialize multiple precision integer
1600  mpiInit(&c);
1601 
1602  //Save the sign of A
1603  sign = a->sign;
1604  //Determine the actual length of A
1605  m = mpiGetBitLength(a);
1606  //Determine the actual length of P
1607  n = mpiGetBitLength(p);
1608 
1609  //Let R = A
1610  MPI_CHECK(mpiCopy(r, a));
1611 
1612  if(m >= n)
1613  {
1614  MPI_CHECK(mpiCopy(&c, p));
1615  MPI_CHECK(mpiShiftLeft(&c, m - n));
1616 
1617  while(mpiCompAbs(r, p) >= 0)
1618  {
1619  if(mpiCompAbs(r, &c) >= 0)
1620  {
1621  MPI_CHECK(mpiSubAbs(r, r, &c));
1622  }
1623 
1624  MPI_CHECK(mpiShiftRight(&c, 1));
1625  }
1626  }
1627 
1628  if(sign < 0)
1629  {
1630  MPI_CHECK(mpiSubAbs(r, p, r));
1631  }
1632 
1633 end:
1634  //Release previously allocated memory
1635  mpiFree(&c);
1636 
1637  //Return status code
1638  return error;
1639 }
1640 
1641 
1642 
1643 /**
1644  * @brief Modular addition
1645  * @param[out] r Resulting integer R = A + B mod P
1646  * @param[in] a The first operand A
1647  * @param[in] b The second operand B
1648  * @param[in] p The modulus P
1649  * @return Error code
1650  **/
1651 
1652 error_t mpiAddMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
1653 {
1654  error_t error;
1655 
1656  //Perform modular addition
1657  MPI_CHECK(mpiAdd(r, a, b));
1658  MPI_CHECK(mpiMod(r, r, p));
1659 
1660 end:
1661  //Return status code
1662  return error;
1663 }
1664 
1665 
1666 /**
1667  * @brief Modular subtraction
1668  * @param[out] r Resulting integer R = A - B mod P
1669  * @param[in] a The first operand A
1670  * @param[in] b The second operand B
1671  * @param[in] p The modulus P
1672  * @return Error code
1673  **/
1674 
1675 error_t mpiSubMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
1676 {
1677  error_t error;
1678 
1679  //Perform modular subtraction
1680  MPI_CHECK(mpiSub(r, a, b));
1681  MPI_CHECK(mpiMod(r, r, p));
1682 
1683 end:
1684  //Return status code
1685  return error;
1686 }
1687 
1688 
1689 /**
1690  * @brief Modular multiplication
1691  * @param[out] r Resulting integer R = A * B mod P
1692  * @param[in] a The first operand A
1693  * @param[in] b The second operand B
1694  * @param[in] p The modulus P
1695  * @return Error code
1696  **/
1697 
1698 __weak_func error_t mpiMulMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
1699 {
1700  error_t error;
1701 
1702  //Perform modular multiplication
1703  MPI_CHECK(mpiMul(r, a, b));
1704  MPI_CHECK(mpiMod(r, r, p));
1705 
1706 end:
1707  //Return status code
1708  return error;
1709 }
1710 
1711 
1712 /**
1713  * @brief Modular inverse
1714  * @param[out] r Resulting integer R = A^-1 mod P
1715  * @param[in] a The multiple precision integer A
1716  * @param[in] p The modulus P
1717  * @return Error code
1718  **/
1719 
1720 __weak_func error_t mpiInvMod(Mpi *r, const Mpi *a, const Mpi *p)
1721 {
1722  error_t error;
1723  Mpi b;
1724  Mpi c;
1725  Mpi q0;
1726  Mpi r0;
1727  Mpi t;
1728  Mpi u;
1729  Mpi v;
1730 
1731  //Initialize multiple precision integers
1732  mpiInit(&b);
1733  mpiInit(&c);
1734  mpiInit(&q0);
1735  mpiInit(&r0);
1736  mpiInit(&t);
1737  mpiInit(&u);
1738  mpiInit(&v);
1739 
1740  MPI_CHECK(mpiCopy(&b, p));
1741  MPI_CHECK(mpiCopy(&c, a));
1742  MPI_CHECK(mpiSetValue(&u, 0));
1743  MPI_CHECK(mpiSetValue(&v, 1));
1744 
1745  while(mpiCompInt(&c, 0) > 0)
1746  {
1747  MPI_CHECK(mpiDiv(&q0, &r0, &b, &c));
1748 
1749  MPI_CHECK(mpiCopy(&b, &c));
1750  MPI_CHECK(mpiCopy(&c, &r0));
1751 
1752  MPI_CHECK(mpiCopy(&t, &v));
1753  MPI_CHECK(mpiMul(&q0, &q0, &v));
1754  MPI_CHECK(mpiSub(&v, &u, &q0));
1755  MPI_CHECK(mpiCopy(&u, &t));
1756  }
1757 
1758  if(mpiCompInt(&b, 1))
1759  {
1761  }
1762 
1763  if(mpiCompInt(&u, 0) > 0)
1764  {
1765  MPI_CHECK(mpiCopy(r, &u));
1766  }
1767  else
1768  {
1769  MPI_CHECK(mpiAdd(r, &u, p));
1770  }
1771 
1772 end:
1773  //Release previously allocated memory
1774  mpiFree(&b);
1775  mpiFree(&c);
1776  mpiFree(&q0);
1777  mpiFree(&r0);
1778  mpiFree(&t);
1779  mpiFree(&u);
1780  mpiFree(&v);
1781 
1782  //Return status code
1783  return error;
1784 }
1785 
1786 
1787 /**
1788  * @brief Modular exponentiation
1789  * @param[out] r Resulting integer R = A ^ E mod P
1790  * @param[in] a Pointer to a multiple precision integer
1791  * @param[in] e Exponent
1792  * @param[in] p Modulus
1793  * @return Error code
1794  **/
1795 
1796 __weak_func error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
1797 {
1798  error_t error;
1799  int_t i;
1800  int_t j;
1801  int_t n;
1802  uint_t d;
1803  uint_t k;
1804  uint_t u;
1805  Mpi b;
1806  Mpi c2;
1807  Mpi t;
1808  Mpi s[8];
1809 
1810  //Initialize multiple precision integers
1811  mpiInit(&b);
1812  mpiInit(&c2);
1813  mpiInit(&t);
1814 
1815  //Initialize precomputed values
1816  for(i = 0; (uint_t) i < arraysize(s); i++)
1817  {
1818  mpiInit(&s[i]);
1819  }
1820 
1821  //Very small exponents are often selected with low Hamming weight. The
1822  //sliding window mechanism should be disabled in that case
1823  d = (mpiGetBitLength(e) <= 32) ? 1 : 4;
1824 
1825  //Even modulus?
1826  if(mpiIsEven(p))
1827  {
1828  //Let S[0] = A
1829  MPI_CHECK(mpiMod(&s[0], a, p));
1830  //Let B = A^2
1831  MPI_CHECK(mpiMulMod(&b, &s[0], &s[0], p));
1832 
1833  //Precompute S[i] = A^(2 * i + 1)
1834  for(i = 1; i < (1 << (d - 1)); i++)
1835  {
1836  MPI_CHECK(mpiMulMod(&s[i], &s[i - 1], &b, p));
1837  }
1838 
1839  //Let R = 1
1840  MPI_CHECK(mpiSetValue(r, 1));
1841 
1842  //The exponent is processed in a left-to-right fashion
1843  i = mpiGetBitLength(e) - 1;
1844 
1845  //Perform sliding window exponentiation
1846  while(i >= 0)
1847  {
1848  //The sliding window exponentiation algorithm decomposes E
1849  //into zero and nonzero windows
1850  if(!mpiGetBitValue(e, i))
1851  {
1852  //Compute R = R^2
1853  MPI_CHECK(mpiMulMod(r, r, r, p));
1854  //Next bit to be processed
1855  i--;
1856  }
1857  else
1858  {
1859  //Find the longest window
1860  n = MAX(i - d + 1, 0);
1861 
1862  //The least significant bit of the window must be equal to 1
1863  while(!mpiGetBitValue(e, n)) n++;
1864 
1865  //The algorithm processes more than one bit per iteration
1866  for(u = 0, j = i; j >= n; j--)
1867  {
1868  //Compute R = R^2
1869  MPI_CHECK(mpiMulMod(r, r, r, p));
1870  //Compute the relevant index to be used in the precomputed table
1871  u = (u << 1) | mpiGetBitValue(e, j);
1872  }
1873 
1874  //Perform a single multiplication per iteration
1875  MPI_CHECK(mpiMulMod(r, r, &s[u >> 1], p));
1876  //Next bit to be processed
1877  i = n - 1;
1878  }
1879  }
1880  }
1881  else
1882  {
1883  //Compute the smaller C = (2^32)^k such as C > P
1884  k = mpiGetLength(p);
1885 
1886  //Compute C^2 mod P
1887  MPI_CHECK(mpiSetValue(&c2, 1));
1888  MPI_CHECK(mpiShiftLeft(&c2, 2 * k * MPI_BITS_PER_WORD));
1889  MPI_CHECK(mpiMod(&c2, &c2, p));
1890 
1891  //Let B = A * C mod P
1892  if(mpiComp(a, p) >= 0)
1893  {
1894  MPI_CHECK(mpiMod(&b, a, p));
1895  MPI_CHECK(mpiMontgomeryMul(&b, &b, &c2, k, p, &t));
1896  }
1897  else
1898  {
1899  MPI_CHECK(mpiMontgomeryMul(&b, a, &c2, k, p, &t));
1900  }
1901 
1902  //Let R = B^2 * C^-1 mod P
1903  MPI_CHECK(mpiMontgomeryMul(r, &b, &b, k, p, &t));
1904  //Let S[0] = B
1905  MPI_CHECK(mpiCopy(&s[0], &b));
1906 
1907  //Precompute S[i] = B^(2 * i + 1) * C^-1 mod P
1908  for(i = 1; i < (1 << (d - 1)); i++)
1909  {
1910  MPI_CHECK(mpiMontgomeryMul(&s[i], &s[i - 1], r, k, p, &t));
1911  }
1912 
1913  //Let R = C mod P
1914  MPI_CHECK(mpiCopy(r, &c2));
1915  MPI_CHECK(mpiMontgomeryRed(r, r, k, p, &t));
1916 
1917  //The exponent is processed in a left-to-right fashion
1918  i = mpiGetBitLength(e) - 1;
1919 
1920  //Perform sliding window exponentiation
1921  while(i >= 0)
1922  {
1923  //The sliding window exponentiation algorithm decomposes E
1924  //into zero and nonzero windows
1925  if(!mpiGetBitValue(e, i))
1926  {
1927  //Compute R = R^2 * C^-1 mod P
1928  MPI_CHECK(mpiMontgomeryMul(r, r, r, k, p, &t));
1929  //Next bit to be processed
1930  i--;
1931  }
1932  else
1933  {
1934  //Find the longest window
1935  n = MAX(i - d + 1, 0);
1936 
1937  //The least significant bit of the window must be equal to 1
1938  while(!mpiGetBitValue(e, n))
1939  {
1940  n++;
1941  }
1942 
1943  //The algorithm processes more than one bit per iteration
1944  for(u = 0, j = i; j >= n; j--)
1945  {
1946  //Compute R = R^2 * C^-1 mod P
1947  MPI_CHECK(mpiMontgomeryMul(r, r, r, k, p, &t));
1948  //Compute the relevant index to be used in the precomputed table
1949  u = (u << 1) | mpiGetBitValue(e, j);
1950  }
1951 
1952  //Compute R = R * T[u/2] * C^-1 mod P
1953  MPI_CHECK(mpiMontgomeryMul(r, r, &s[u >> 1], k, p, &t));
1954  //Next bit to be processed
1955  i = n - 1;
1956  }
1957  }
1958 
1959  //Compute R = R * C^-1 mod P
1960  MPI_CHECK(mpiMontgomeryRed(r, r, k, p, &t));
1961  }
1962 
1963 end:
1964  //Release multiple precision integers
1965  mpiFree(&b);
1966  mpiFree(&c2);
1967  mpiFree(&t);
1968 
1969  //Release precomputed values
1970  for(i = 0; (uint_t) i < arraysize(s); i++)
1971  {
1972  mpiFree(&s[i]);
1973  }
1974 
1975  //Return status code
1976  return error;
1977 }
1978 
1979 
1980 /**
1981  * @brief Modular exponentiation (fast calculation)
1982  * @param[out] r Resulting integer R = A ^ E mod P
1983  * @param[in] a Pointer to a multiple precision integer
1984  * @param[in] e Exponent
1985  * @param[in] p Modulus
1986  * @return Error code
1987  **/
1988 
1989 __weak_func error_t mpiExpModFast(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
1990 {
1991  //Perform modular exponentiation
1992  return mpiExpMod(r, a, e, p);
1993 }
1994 
1995 
1996 /**
1997  * @brief Modular exponentiation (regular calculation)
1998  * @param[out] r Resulting integer R = A ^ E mod P
1999  * @param[in] a Pointer to a multiple precision integer
2000  * @param[in] e Exponent
2001  * @param[in] p Modulus
2002  * @return Error code
2003  **/
2004 
2005 __weak_func error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
2006 {
2007  //Perform modular exponentiation
2008  return mpiExpMod(r, a, e, p);
2009 }
2010 
2011 
2012 /**
2013  * @brief Montgomery multiplication
2014  * @param[out] r Resulting integer R = A * B / 2^k mod P
2015  * @param[in] a An integer A such as 0 <= A < 2^k
2016  * @param[in] b An integer B such as 0 <= B < 2^k
2017  * @param[in] k An integer k such as P < 2^k
2018  * @param[in] p Modulus P
2019  * @param[in] t An preallocated integer T (for internal operation)
2020  * @return Error code
2021  **/
2022 
2023 error_t mpiMontgomeryMul(Mpi *r, const Mpi *a, const Mpi *b, uint_t k,
2024  const Mpi *p, Mpi *t)
2025 {
2026  error_t error;
2027  uint_t i;
2028  uint_t n;
2029  mpi_word_t m;
2030  mpi_word_t q;
2031 
2032  //Use Newton's method to compute the inverse of P[0] mod 2^32
2033  for(m = p->data[0], i = 0; i < 4; i++)
2034  {
2035  m = m * (2U - m * p->data[0]);
2036  }
2037 
2038  //Precompute -1/P[0] mod 2^32;
2039  m = ~m + 1U;
2040 
2041  //We assume that B is always less than 2^k
2042  n = MIN(b->size, k);
2043 
2044  //Make sure T is large enough
2045  MPI_CHECK(mpiGrow(t, 2 * k + 1));
2046  //Let T = 0
2047  MPI_CHECK(mpiSetValue(t, 0));
2048 
2049  //Perform Montgomery multiplication
2050  for(i = 0; i < k; i++)
2051  {
2052  //Check current index
2053  if(i < a->size)
2054  {
2055  //Compute q = ((T[i] + A[i] * B[0]) * m) mod 2^32
2056  q = (t->data[i] + a->data[i] * b->data[0]) * m;
2057  //Compute T = T + A[i] * B
2058  mpiMulAccCore(t->data + i, b->data, n, a->data[i]);
2059  }
2060  else
2061  {
2062  //Compute q = (T[i] * m) mod 2^32
2063  q = t->data[i] * m;
2064  }
2065 
2066  //Compute T = T + q * P
2067  mpiMulAccCore(t->data + i, p->data, k, q);
2068  }
2069 
2070  //Compute R = T / 2^(32 * k)
2072  MPI_CHECK(mpiCopy(r, t));
2073 
2074  //A final subtraction is required
2075  if(mpiComp(r, p) >= 0)
2076  {
2077  MPI_CHECK(mpiSub(r, r, p));
2078  }
2079 
2080 end:
2081  //Return status code
2082  return error;
2083 }
2084 
2085 
2086 /**
2087  * @brief Montgomery reduction
2088  * @param[out] r Resulting integer R = A / 2^k mod P
2089  * @param[in] a An integer A such as 0 <= A < 2^k
2090  * @param[in] k An integer k such as P < 2^k
2091  * @param[in] p Modulus P
2092  * @param[in] t An preallocated integer T (for internal operation)
2093  * @return Error code
2094  **/
2095 
2096 error_t mpiMontgomeryRed(Mpi *r, const Mpi *a, uint_t k, const Mpi *p, Mpi *t)
2097 {
2098  mpi_word_t value;
2099  Mpi b;
2100 
2101  //Let B = 1
2102  value = 1;
2103  b.sign = 1;
2104  b.size = 1;
2105 
2106 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
2107  b.data = &value;
2108 #else
2109  b.data[0] = value;
2110 #endif
2111 
2112  //Compute R = A / 2^k mod P
2113  return mpiMontgomeryMul(r, a, &b, k, p, t);
2114 }
2115 
2116 
2117 #if (MPI_ASM_SUPPORT == DISABLED)
2118 
2119 /**
2120  * @brief Multiply-accumulate operation
2121  * @param[out] r Resulting integer
2122  * @param[in] a First operand A
2123  * @param[in] m Size of A in words
2124  * @param[in] b Second operand B
2125  **/
2126 
2128  const mpi_word_t b)
2129 {
2130  int_t i;
2131  mpi_word_t c;
2132  mpi_word_t u;
2133  mpi_word_t v;
2134  mpi_dword_t p;
2135 
2136  //Clear variables
2137  c = 0;
2138  u = 0;
2139  v = 0;
2140 
2141  //Perform multiplication
2142  for(i = 0; i < m; i++)
2143  {
2144  p = (mpi_dword_t) a[i] * b;
2145  u = (mpi_word_t) p;
2146  v = (mpi_word_t) (p >> MPI_BITS_PER_WORD);
2147 
2148  u += c;
2149 
2150  if(u < c)
2151  {
2152  v++;
2153  }
2154 
2155  u += r[i];
2156 
2157  if(u < r[i])
2158  {
2159  v++;
2160  }
2161 
2162  r[i] = u;
2163  c = v;
2164  }
2165 
2166  //Propagate carry
2167  for(; c != 0; i++)
2168  {
2169  r[i] += c;
2170  c = (r[i] < c);
2171  }
2172 }
2173 
2174 #endif
2175 
2176 
2177 /**
2178  * @brief Display the contents of a multiple precision integer
2179  * @param[in] stream Pointer to a FILE object that identifies an output stream
2180  * @param[in] prepend String to prepend to the left of each line
2181  * @param[in] a Pointer to a multiple precision integer
2182  **/
2183 
2184 void mpiDump(FILE *stream, const char_t *prepend, const Mpi *a)
2185 {
2186  uint_t i;
2187 
2188  //Process each word
2189  for(i = 0; i < a->size; i++)
2190  {
2191  //Beginning of a new line?
2192  if(i == 0 || ((a->size - i - 1) % 8) == 7)
2193  {
2194  fprintf(stream, "%s", prepend);
2195  }
2196 
2197  //Display current data
2198  fprintf(stream, "%08X ", a->data[a->size - 1 - i]);
2199 
2200  //End of current line?
2201  if(((a->size - i - 1) % 8) == 0 || i == (a->size - 1))
2202  {
2203  fprintf(stream, "\r\n");
2204  }
2205  }
2206 }
2207 
2208 #endif
error_t mpiShiftLeft(Mpi *r, uint_t n)
Left shift operation.
Definition: mpi.c:1243
__weak_func error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation.
Definition: mpi.c:1796
uint8_t b
Definition: nbns_common.h:104
uint8_t a
Definition: ndp.h:411
Arbitrary precision integer.
Definition: mpi.h:102
signed int int_t
Definition: compiler_port.h:56
void mpiMulAccCore(mpi_word_t *r, const mpi_word_t *a, int_t m, const mpi_word_t b)
Multiply-accumulate operation.
Definition: mpi.c:2127
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:143
error_t mpiMontgomeryRed(Mpi *r, const Mpi *a, uint_t k, const Mpi *p, Mpi *t)
Montgomery reduction.
Definition: mpi.c:2096
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
#define PrngAlgo
Definition: crypto.h:973
error_t mpiSubAbs(Mpi *r, const Mpi *a, const Mpi *b)
Helper routine for multiple precision subtraction.
Definition: mpi.c:1141
uint8_t p
Definition: ndp.h:300
uint8_t t
Definition: lldp_ext_med.h:212
uint8_t data[]
Definition: ethernet.h:222
__weak_func error_t mpiMulMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
Modular multiplication.
Definition: mpi.c:1698
#define mpiIsEven(a)
Definition: mpi.h:77
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
error_t mpiSetBitValue(Mpi *r, uint_t index, uint_t value)
Set the bit value at the specified index.
Definition: mpi.c:295
error_t mpiAddAbs(Mpi *r, const Mpi *a, const Mpi *b)
Helper routine for multiple precision addition.
Definition: mpi.c:1047
void mpiDump(FILE *stream, const char_t *prepend, const Mpi *a)
Display the contents of a multiple precision integer.
Definition: mpi.c:2184
error_t mpiRandRange(Mpi *r, const Mpi *p, const PrngAlgo *prngAlgo, void *prngContext)
Generate a random value in the range 1 to p-1.
Definition: mpi.c:652
error_t mpiShiftRight(Mpi *r, uint_t n)
Right shift operation.
Definition: mpi.c:1310
error_t mpiRand(Mpi *r, uint_t length, const PrngAlgo *prngAlgo, void *prngContext)
Generate a random value.
Definition: mpi.c:598
int_t mpiCompAbs(const Mpi *a, const Mpi *b)
Compare the absolute value of two multiple precision integers.
Definition: mpi.c:457
error_t mpiSubInt(Mpi *r, const Mpi *a, mpi_sword_t b)
Subtract an integer from a multiple precision integer.
Definition: mpi.c:1018
const uint8_t res[]
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:48
uint8_t r
Definition: ndp.h:346
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1587
error_t mpiMulInt(Mpi *r, const Mpi *a, mpi_sword_t b)
Multiply a multiple precision integer by an integer.
Definition: mpi.c:1455
__weak_func error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation (regular calculation)
Definition: mpi.c:2005
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t mpiSubMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
Modular subtraction.
Definition: mpi.c:1675
error_t mpiSub(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision subtraction.
Definition: mpi.c:969
__weak_func error_t mpiInvMod(Mpi *r, const Mpi *a, const Mpi *p)
Modular inverse.
Definition: mpi.c:1720
@ MPI_FORMAT_LITTLE_ENDIAN
Definition: mpi.h:92
error_t
Error codes.
Definition: error.h:43
error_t mpiSetValue(Mpi *r, mpi_sword_t a)
Set the value of a multiple precision integer.
Definition: mpi.c:562
error_t mpiAddInt(Mpi *r, const Mpi *a, mpi_sword_t b)
Add an integer to a multiple precision integer.
Definition: mpi.c:940
#define MPI_CHECK(f)
Definition: mpi.h:74
error_t mpiAdd(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision addition.
Definition: mpi.c:891
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define MPI_BYTES_PER_WORD
Definition: mpi.h:56
error_t mpiImport(Mpi *r, const uint8_t *input, size_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:712
MPI (Multiple Precision Integer Arithmetic)
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define mpi_dword_t
Definition: mpi.h:70
General definitions for cryptographic algorithms.
uint8_t u
Definition: lldp_ext_med.h:213
error_t mpiExport(const Mpi *a, uint8_t *output, size_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:809
uint8_t length
Definition: tcp.h:375
#define MPI_BITS_PER_WORD
Definition: mpi.h:47
#define MIN(a, b)
Definition: os_port.h:63
error_t mpiDiv(Mpi *q, Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision division.
Definition: mpi.c:1485
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:254
#define mpi_word_t
Definition: mpi.h:68
error_t mpiCopy(Mpi *r, const Mpi *a)
Copy a multiple precision integer.
Definition: mpi.c:516
MpiFormat
MPI import/export format.
Definition: mpi.h:91
#define MAX(a, b)
Definition: os_port.h:67
uint_t mpiGetLength(const Mpi *a)
Get the actual length in words.
Definition: mpi.c:188
char char_t
Definition: compiler_port.h:55
error_t mpiMontgomeryMul(Mpi *r, const Mpi *a, const Mpi *b, uint_t k, const Mpi *p, Mpi *t)
Montgomery multiplication.
Definition: mpi.c:2023
error_t mpiDivInt(Mpi *q, Mpi *r, const Mpi *a, mpi_sword_t b)
Divide a multiple precision integer by an integer.
Definition: mpi.c:1558
uint8_t m
Definition: ndp.h:304
uint8_t n
#define MPI_MAX_WORDS
Definition: mpi.h:53
#define cryptoFreeMem(p)
Definition: crypto.h:826
uint8_t value[]
Definition: tcp.h:376
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:93
#define cryptoAllocMem(size)
Definition: crypto.h:821
uint8_t s
Definition: igmp_common.h:234
int_t mpiComp(const Mpi *a, const Mpi *b)
Compare two multiple precision integers.
Definition: mpi.c:358
#define mpi_sword_t
Definition: mpi.h:69
int_t mpiCompInt(const Mpi *a, mpi_sword_t b)
Compare a multiple precision integer with an integer.
Definition: mpi.c:429
unsigned int uint_t
Definition: compiler_port.h:57
__weak_func error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision multiplication.
Definition: mpi.c:1375
#define osMemset(p, value, length)
Definition: os_port.h:138
uint_t mpiGetBitValue(const Mpi *a, uint_t index)
Get the bit value at the specified index.
Definition: mpi.c:333
error_t mpiAddMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
Modular addition.
Definition: mpi.c:1652
error_t mpiGrow(Mpi *r, uint_t size)
Adjust the size of multiple precision integer.
Definition: mpi.c:102
__weak_func error_t mpiExpModFast(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation (fast calculation)
Definition: mpi.c:1989
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.
#define arraysize(a)
Definition: os_port.h:71
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:215
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:64
__weak_func error_t mpiCheckProbablePrime(const Mpi *a)
Test whether a number is probable prime.
Definition: mpi.c:693