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