MPHELL  4.0.0
mphell-number.c
Go to the documentation of this file.
1 /*
2  MPHELL-4.0
3  Author(s): The MPHELL team
4 
5  (C) Copyright 2015-2018 - Institut Fourier / Univ. Grenoble Alpes (France)
6 
7  This file is part of the MPHELL Library.
8  MPHELL is free software: you can redistribute it and/or modify
9  it under the terms of the GNU Lesser General Public License as published by
10  the Free Software Foundation, version 3 of the License.
11 
12  MPHELL is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with MPHELL. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
26 #include "mphell-number.h"
27 
28 /*********************************** TMP ALLOC *******************************/
29 
30 void
31 number_tmp_alloc (number * t, const uint8_t size, uint8_t stack)
32 {
33 #if MPHELL_USE_GMP == 1
34  /* We cannot handle GMP realloc, and LIMBS_PER_DIGIT_IN_BASE macro,
35  * used in mpz_set_str can create realloc when the alloc size is < size +2 */
36  gmp_tmp_alloc((number_ptr)(*t), size+2, stack);
37 #elif MPHELL_USE_IPP == 1
38  ippcp_bn_tmp_alloc(t, size, stack);
39 #elif MPHELL_USE_MBEDTLS == 1
40  mbedtls_tmp_alloc((number_ptr)(*t), size, stack);
41 #endif
42 }
43 
44 void
45 number_tmp_free (number * t, const uint8_t size, uint8_t stack)
46 {
47 #if MPHELL_USE_GMP == 1
48  gmp_tmp_free((number_ptr)(*t), size+2, stack);
49 #elif MPHELL_USE_IPP == 1
50  ippcp_bn_tmp_free(t, size, stack);
51 #elif MPHELL_USE_MBEDTLS == 1
52  mbedtls_tmp_free((number_ptr)(*t), size, stack);
53 #endif
54 }
55 
56 /************************************ SETTERS ********************************/
57 
58 void
59 number_init (number * dst, const uint8_t n)
60 {
61 #if MPHELL_USE_GMP == 1
62  mpz_init2(*dst, BLOCK_SIZE * n);
63 #elif MPHELL_USE_IPP == 1
64  int ctxSize;
65  ippsBigNumGetSize(n, &ctxSize);
66  *dst = (IppsBigNumState*)malloc(ctxSize*sizeof(Ipp8u));
67  ippsBigNumInit(n, *dst); /* Works with 32 bits blocks */
68 #elif MPHELL_USE_MBEDTLS == 1
69  mbedtls_mpi_init(*dst);
70  mbedtls_mpi_grow(*dst, n);
71 #endif
72 }
73 
74 void
75 number_free (number * dst)
76 {
77 #if MPHELL_USE_GMP == 1
78  mpz_clear(*dst);
79 #elif MPHELL_USE_IPP == 1
80  free(*dst);
81 #elif MPHELL_USE_MBEDTLS == 1
82  mbedtls_mpi_free(*dst);
83 #endif
84 }
85 
86 void
87 number_copy (number_ptr dst, number_srcptr src)
88 {
89 #if MPHELL_USE_GMP == 1
90  mpz_set(dst, src);
91 #elif MPHELL_USE_IPP == 1
92  int len;
93  IppsBigNumSGN sgn;
94  Ipp32u * data;
95  ippsRef_BN(&sgn, &len, &data, src);
96  ippsSet_BN(sgn, bits_to_nblock(len), data, dst);
97 #elif MPHELL_USE_MBEDTLS == 1
98  mbedtls_mpi_copy(dst, src);
99 #endif
100 }
101 
102 void
103 number_set_ui (number_ptr dst, const block src)
104 {
105 #if MPHELL_USE_GMP == 1
106  mpz_set_ui(dst, src);
107 #elif MPHELL_USE_IPP == 1
108  ippsSet_BN(ippBigNumPOS, 1, (Ipp32u *)(&src), dst);
109 #elif MPHELL_USE_MBEDTLS == 1
110  //mbedtls_mpi_lset(dst, (mbedtls_mpi_sint)src);
111  memset(dst->p, 0, dst->n * BYTES_PER_LIMB);
112  dst->p[0] = src;
113  dst->s = 1;
114 #endif
115 }
116 
117 void
118 number_set (number_ptr dst, const int8_t sign, const uint32_t size, ...)
119 {
120 #if MPHELL_USE_GMP == 1
121  va_list ap;
122  uint8_t i;
123 
124  va_start(ap, size);
125  uint8_t n = ALLOC_SIZ(dst);
126  for(i = 0; i < n; i++)
127  {
128  if(i < size)
129  {
130  LIMB(dst)[i] = (block)va_arg(ap, block);
131  }
132  else
133  {
134  LIMB(dst)[i] = (block)0;
135  }
136  }
137  va_end(ap);
138 
139  SIZ(dst) = size;
140 
141  if(sign < 0)
142  {
143  dst->_mp_size *= -1;
144  }
145 #elif MPHELL_USE_IPP == 1
146  va_list ap;
147  va_start(ap, size);
148  Ipp32u temp[18];
149  uint8_t i;
150  for(i = 0; i < size; i++)
151  {
152  temp[i]=va_arg(ap, Ipp32u);
153  }
154  if(sign < 0)
155  {
156  ippsSet_BN(ippBigNumNEG, size, temp, dst);
157  }
158  else
159  {
160  ippsSet_BN(ippBigNumPOS, size, temp, dst);
161  }
162  va_end(ap);
163 #elif MPHELL_USE_MBEDTLS == 1
164  va_list ap;
165  uint8_t i;
166  mbedtls_mpi_lset(dst, 0);
167  va_start(ap, size);
168  dst->s = sign;
169  for(i=0; i<size; i++)
170  {
171  dst->p[i] = (block)va_arg(ap, block);
172  }
173  va_end(ap);
174 #endif
175 }
176 
177 void
178 number_set_bit (number_ptr dst, const uint32_t bit)
179 {
180 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_IPP == 1)
181  uint8_t q = bit / BLOCK_SIZE;
182  uint8_t r = bit % BLOCK_SIZE;
183  uint8_t size = bits_to_nblock(bit+1);
184 #endif
185 #if MPHELL_USE_GMP == 1
186  memset(LIMB(dst), 0, size * BYTES_PER_LIMB);
187  LIMB(dst)[q] = (mp_limb_t)1 << r;
188  SIZ(dst) = size;
189 #elif MPHELL_USE_IPP == 1
190  Ipp32u data[size];
191  memset(data, 0, size * BYTES_PER_LIMB);
192  data[q] = (Ipp32u)1 << r;
193  ippsSet_BN(IppsBigNumPOS, size, data, dst);
194 #elif MPHELL_USE_MBEDTLS == 1
195  mbedtls_mpi_set_bit(dst, bit, 1);
196 #endif
197 }
198 
199 void
200 number_random (number_ptr dst, const uint32_t size)
201 {
202 #if MPHELL_USE_GMP == 1
203 #if BLOCK_SIZE == 64
204  mphell_rng(NULL, (unsigned char *)LIMB(dst), size*8);
205 #else
206  mphell_rng(NULL, (unsigned char *)LIMB(dst), size*4);
207 #endif
208  SIZ(dst) = size;
209 #elif MPHELL_USE_IPP == 1
210  /* Get number of 32bits words dst can store */
211  Ipp32u temp[size];
212  mphell_rng(NULL, (unsigned char *)temp, size*4);
213  ippsSet_BN(ippBigNumPOS, size, temp, dst);
214 #elif MPHELL_USE_MBEDTLS == 1
215  /* Get number of 32bits words dst can store */
216 #if BLOCK_SIZE == 64
217  mphell_rng(NULL, (unsigned char *)dst->p, size*8);
218 #else
219  mphell_rng(NULL, (unsigned char *)dst->p, size*4);
220 #endif
221  uint8_t i;
222  for(i = size; i < dst->n; i++)
223  {
224  dst->p[i] = 0;
225  }
226 #endif
227 }
228 
229 void
230 number_random1 (number_ptr dst, number_srcptr bound, uint8_t stack)
231 {
232  number mask;
233  int size;
234 #if MPHELL_USE_GMP == 1
235  size = SIZ(bound);
236 #elif MPHELL_USE_IPP == 1
237  ippsRef_BN(NULL, &size, NULL, bound);
238  size = bits_to_nblock(size);
239 #elif MPHELL_USE_MBEDTLS == 1
240  size = bound->n;
241 #endif
242  number_tmp_alloc(&mask, size+1, stack);
243  number_set_ui(mask, 0);
244  uint16_t srcbits = number_log2(bound);
245  number_set_bit(mask, srcbits);
246  number_dec(mask, mask);
247  do {
248  number_random(dst, size);
249  number_and(dst, dst, mask);
250  } while (number_isgreatereq(dst, bound));
251  number_tmp_free(&mask, size+1, stack);
252 }
253 
254 /*********************************** STRING **********************************/
255 
256 uint16_t
257 number_log2 (number_srcptr src)
258 {
259 #if MPHELL_USE_GMP == 1
260  return (uint16_t)mpz_sizeinbase(src, 2);
261 #elif MPHELL_USE_IPP == 1
262  int size;
263  ippsExtGet_BN(NULL, &size, NULL, src);
264  return size;
265 #elif MPHELL_USE_MBEDTLS == 1
266  return mbedtls_mpi_bitlen(src);
267 #endif
268 }
269 
270 uint8_t
271 number_block_size (number_srcptr src)
272 {
273 #if MPHELL_USE_GMP == 1
274  return src->_mp_size;
275 #elif MPHELL_USE_IPP == 1
276  int size;
277  ippsExtGet_BN(NULL, &size, NULL, src);
278  return bits_to_nblock(size);
279 #elif MPHELL_USE_MBEDTLS == 1
280  return src->n;
281 #endif
282 }
283 
284 uint8_t
285 number_buffer_size (number_srcptr src)
286 {
287 #if MPHELL_USE_GMP == 1
288  return src->_mp_alloc;
289 #elif MPHELL_USE_IPP == 1
290  int size;
291  ippsGetSize_BN(src, &size);
292  return size;
293 #elif MPHELL_USE_MBEDTLS == 1
294  return src->n;
295 #endif
296 }
297 
298 void
299 number_set_str (number_ptr dst, const char *str, const uint8_t base)
300 {
301 #if MPHELL_USE_GMP == 1
302  mpz_set_str(dst, str, base);
303 #elif MPHELL_USE_IPP == 1
304  int16_t i, j;
305  int16_t len, len_chunk, lentmp;
306  if(base == 2)
307  {
308  len = strlen(str);
309  lentmp = len;
310  len_chunk = bits_to_nblock(len); /* Number of 32 bits blocks */
311  Ipp32u data[len_chunk];
312  memset(data, 0, len_chunk * 4);
313  for(i=0; i<len_chunk; i++)
314  {
315  for(j=0; j<32; j++)
316  {
317  if(i*32+j<len)
318  {
319  --lentmp;
320  if(str[lentmp]=='1')
321  {
322  data[i]^=((Ipp32u)1<<j);
323  }
324  }
325  }
326  }
327  ippsSet_BN(IppsBigNumPOS, len_chunk, data, dst);
328  }
329  else if(base == 10)
330  {
331  len = strlen(str);
332  int i = 0;
333  number_set_ui(dst, str[i++]-'0');
334  while(i < len)
335  {
336  number_mul_ui(dst, dst, 10);
337  number_add_ui(dst, dst, str[i++]-'0');
338  }
339  }
340  else if(base == 16)
341  {
342  char * tab[16]={"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
343  j=0;
344  len = strlen(str)*4; /* Binary size */
345  char str2[len+1];
346  for(i=0; i<strlen(str); i++)
347  {
348  if(str[i]=='0')
349  {
350  memcpy(str2+j, tab[0], 4);
351  }
352  else if(str[i]=='1')
353  {
354  memcpy(str2+j, tab[1], 4);
355  }
356  else if(str[i]=='2')
357  {
358  memcpy(str2+j, tab[2], 4);
359  }
360  else if(str[i]=='3')
361  {
362  memcpy(str2+j, tab[3], 4);
363  }
364  else if(str[i]=='4')
365  {
366  memcpy(str2+j, tab[4], 4);
367  }
368  else if(str[i]=='5')
369  {
370  memcpy(str2+j, tab[5], 4);
371  }
372  else if(str[i]=='6')
373  {
374  memcpy(str2+j, tab[6], 4);
375  }
376  else if(str[i]=='7')
377  {
378  memcpy(str2+j, tab[7], 4);
379  }
380  else if(str[i]=='8')
381  {
382  memcpy(str2+j, tab[8], 4);
383  }
384  else if(str[i]=='9')
385  {
386  memcpy(str2+j, tab[9], 4);
387  }
388  else if(str[i]=='a' || str[i]=='A')
389  {
390  memcpy(str2+j, tab[10], 4);
391  }
392  else if(str[i]=='b' || str[i]=='B')
393  {
394  memcpy(str2+j, tab[11], 4);
395  }
396  else if(str[i]=='c' || str[i]=='C')
397  {
398  memcpy(str2+j, tab[12], 4);
399  }
400  else if(str[i]=='d' || str[i]=='D')
401  {
402  memcpy(str2+j, tab[13], 4);
403  }
404  else if(str[i]=='e' || str[i]=='E')
405  {
406  memcpy(str2+j, tab[14], 4);
407  }
408  else if(str[i]=='f' || str[i]=='F')
409  {
410  memcpy(str2+j, tab[15], 4);
411  }
412  else
413  {
414  /* Unknow character */
415  break;
416  }
417  j+=4;
418  }
419  str2[j]='\0';
420  number_set_str(dst, str2, 2);
421  }
422  else
423  {
424  mphell_error ("Error in number_set_str, base must be either 2, 10 or 16\n");
425  }
426 #elif MPHELL_USE_MBEDTLS == 1
427  mbedtls_mpi_lset(dst, 0);
428  if(str[strlen(str)-1]=='\n')
429  {
430  uint16_t s = strlen(str);
431  char tmp[s];
432  memcpy(tmp, str, s-1);
433  tmp[s-1]='\0'; /* Replace '\n' by '\0' */
434  mbedtls_mpi_read_string(dst, base, tmp);
435  }
436  else
437  {
438  mbedtls_mpi_read_string(dst, base, str);
439  }
440 #endif
441 }
442 
443 void
444 number_str (char **str, number_srcptr src, const uint8_t base)
445 {
446 #if MPHELL_USE_GMP == 1
447  if(base == 16)
448  {
449  gmp_asprintf(str, "%Zx", src);
450  }
451  else if (base == 10)
452  {
453  gmp_asprintf(str, "%Zd", src);
454  }
455  else
456  {
457  *str = mpz_get_str (NULL, base, src);
458  }
459 #elif MPHELL_USE_IPP == 1
460  if(number_iszero(src))
461  {
462  *str = (char *)malloc(2*sizeof(char));
463  (*str)[0]='0';
464  (*str)[1]='\0';
465  }
466  else
467  {
468  if(base == 2)
469  {
470  int8_t i;
471  uint32_t j = 0;
472  int len;
473  int len32;
474  IppsBigNumSGN sgn;
475  Ipp32u * data;
476  ippsRef_BN(&sgn, &len, &data, src);
477  len32 = bits_to_nblock(len);
478  char * pstr;
479  if(sgn==IppsBigNumNEG)
480  {
481  *str = (char *)malloc((len+2)*sizeof(char));
482  (*str)[0]='-';
483  pstr = *str+1;
484  (*str)[len+1]='\0';
485  }
486  else
487  {
488  *str = (char *)malloc((len+1)*sizeof(char));
489  pstr = *str;
490  (*str)[len]='\0';
491  }
492  for(i=0; i<len32; i++)
493  {
494  for(j=0; j<32; j++)
495  {
496  if(len > 0)
497  {
498  if(data[i] & (Ipp32u)1<<j)
499  {
500  pstr[--len]='1';
501  }
502  else
503  {
504  pstr[--len]='0';
505  }
506  }
507  else
508  {
509  break;
510  }
511  }
512  }
513  }
514  else if (base == 10)
515  {
516  int i;
517  int len;
518  int len32;
519  IppsBigNumSGN sgn;
520  Ipp32u * data;
521  ippsRef_BN(&sgn, &len, &data, src);
522  len32 = bits_to_nblock(len);
523  char * pstr;
524  char tab[len32*10];
525  number tmp;
526  number_init(&tmp, len32);
527  ippsSet_BN(IppsBigNumPOS, len32, data, tmp);
528 
529  int it = 0;
530  block digit;
531  while(!number_iszero(tmp))
532  {
533  number_mod_ui(&digit, tmp, 10);
534  tab[it++]=digit + '0';
535  number_div_ui(tmp, tmp, 10);
536  }
537  number_free(&tmp);
538  if(sgn==IppsBigNumNEG)
539  {
540  *str = (char *)malloc((it+2)*sizeof(char));
541  (*str)[0]='-';
542  pstr = *str+1;
543  }
544  else
545  {
546  *str = (char *)malloc((it+1)*sizeof(char));
547  pstr = *str;
548  }
549  for(i = 0; i<it; i++)
550  {
551  pstr[i]=tab[it-i-1];
552  }
553  pstr[i]='\0';
554  }
555  else if (base == 16)
556  {
557  char tab[16]={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
558  int8_t i;
559  uint32_t j = 0;
560  int8_t k = 0;
561  int len;
562  int len32;
563  int len4;
564  IppsBigNumSGN sgn;
565  Ipp32u * data;
566  ippsRef_BN(&sgn, &len, &data, src);
567  len32 = bits_to_nblock(len);
568  len4 = ((len / 4) + ((len % 4) != 0));
569  char * pstr;
570  if(sgn==IppsBigNumNEG)
571  {
572  *str = (char *)malloc((len4+2)*sizeof(char));
573  (*str)[0]='-';
574  pstr = *str+1;
575  (*str)[len4+1]='\0';
576  }
577  else
578  {
579  *str = (char *)malloc((len4+1)*sizeof(char));
580  pstr = *str;
581  (*str)[len4]='\0';
582  }
583  for(i=0; i<len32; i++)
584  {
585  for(j=0; j<32; j+=4)
586  {
587  if(len4 > 0)
588  {
589  k=0;
590  if(data[i] & (Ipp32u)1<<j)
591  {
592  k+=1;
593  }
594  if(data[i] & (Ipp32u)1<<(j+1))
595  {
596  k+=2;
597  }
598  if(data[i] & (Ipp32u)1<<(j+2))
599  {
600  k+=4;
601  }
602  if(data[i] & (Ipp32u)1<<(j+3))
603  {
604  k+=8;
605  }
606  pstr[--len4]=tab[k];
607  }
608  }
609  }
610  }
611  else
612  {
613  mphell_error ("Error in number_str, base must be either 2, 10 or 16\n");
614  }
615  }
616 #elif MPHELL_USE_MBEDTLS == 1
617  size_t size = mbedtls_mpi_bitlen(src);
618  if( base == 10 )
619  {
620  size >>= 1;
621  }
622  if( base >= 16 )
623  {
624  size >>= 1;
625  }
626  size += 4;
627  size_t outlen;
628  *str = (char *)malloc(size*sizeof(char));
629  mbedtls_mpi_write_string(src, base, *str, size, &outlen);
630  if(((*str)[0]=='0' && outlen > 2) || ((*str)[0]=='-' && (*str)[1]=='0' && outlen > 3))
631  {
632  if((*str)[0]=='-')
633  {
634  size = 1;
635  }
636  else
637  {
638  size = 0;
639  }
640  for(; size < outlen-1; size++)
641  {
642  (*str)[size]=(*str)[size+1];
643  }
644  }
645 #endif
646 }
647 
648 void
649 number_get_ui (block * dst, number_srcptr src)
650 {
651 #if MPHELL_USE_GMP == 1
652  *dst = mpz_get_ui(src);
653 #elif MPHELL_USE_IPP == 1
654  int len;
655  IppsBigNumSGN sgn;
656  Ipp32u * data;
657  ippsRef_BN(&sgn, &len, &data, src);
658  *dst = data[0];
659 #elif MPHELL_USE_MBEDTLS == 1
660  *dst = src->p[0];
661 #endif
662 }
663 
664 void
665 number_to_bit_string (char *str, number_srcptr src)
666 {
667 #if MPHELL_USE_GMP == 1
668  mpz_get_str (str, 2, src);
669 #elif MPHELL_USE_IPP == 1
670  if(number_iszero(src))
671  {
672  str[0]='0';
673  str[1]='\0';
674  }
675  else
676  {
677  int8_t i;
678  uint32_t j = 0;
679  int len;
680  int len32;
681  IppsBigNumSGN sgn;
682  Ipp32u * data;
683  ippsRef_BN(&sgn, &len, &data, src);
684  len32 = bits_to_nblock(len);
685  str[len]='\0';
686  for(i=0; i<len32; i++)
687  {
688  for(j=0; j<32; j++)
689  {
690  if(len > 0)
691  {
692  if(data[i] & (Ipp32u)1<<j)
693  {
694  str[--len]='1';
695  }
696  else
697  {
698  str[--len]='0';
699  }
700  }
701  else
702  {
703  break;
704  }
705  }
706  }
707  }
708 #elif MPHELL_USE_MBEDTLS == 1
709  size_t size = mbedtls_mpi_bitlen(src)+4;
710  mbedtls_mpi_write_string(src, 2, str, size, &size);
711 #endif
712 }
713 
714 void
715 number_print (number_srcptr src, const uint8_t base)
716 {
717 #if MPHELL_USE_GMP == 1
718  if(base == 16)
719  {
720  gmp_printf("%Zx", src);
721  }
722  else if (base == 10)
723  {
724  gmp_printf("%Zd", src);
725  }
726  else
727  {
728  char * str;
729  number_str(&str, src, base);
730  printf("%s", str);
731  free(str);
732  }
733 #elif (MPHELL_USE_IPP == 1 || MPHELL_USE_MBEDTLS == 1)
734  char * str;
735  number_str(&str, src, base);
736  printf("%s", str);
737  free(str);
738 #endif
739 }
740 
741 /*********************************** COMPARISON ******************************/
742 
743 bool
744 number_iszero(number_srcptr src)
745 {
746 #if MPHELL_USE_GMP == 1
747  return (mpz_cmp_ui(src, (block)0) == 0);
748 #elif MPHELL_USE_IPP == 1
749  Ipp32u test;
750  ippsCmpZero_BN(src, &test);
751  return (test==IS_ZERO);
752 #elif MPHELL_USE_MBEDTLS == 1
753  return (mbedtls_mpi_cmp_int(src, 0) == 0);
754 #endif
755 }
756 
757 bool
758 number_isequal_ui (number_srcptr src1, const block src2)
759 {
760 #if MPHELL_USE_GMP == 1
761  return (mpz_cmp_ui(src1, src2) == 0);
762 #elif MPHELL_USE_IPP == 1
763  int len;
764  IppsBigNumSGN sgn;
765  Ipp32u * data;
766  ippsRef_BN(&sgn, &len, &data, src1);
767  if((sgn == IppsBigNumNEG) || (len > 32) || (data[0]!=(Ipp32u)src2))
768  {
769  return false;
770  }
771  else
772  {
773  return true;
774  }
775 #elif MPHELL_USE_MBEDTLS == 1
776  return (mbedtls_mpi_cmp_int(src1, (mbedtls_mpi_sint)src2) == 0);
777 #endif
778 }
779 
780 bool
781 number_isequal (number_srcptr src1, number_srcptr src2)
782 {
783 #if MPHELL_USE_GMP == 1
784  return (mpz_cmp(src1, src2) == 0);
785 #elif MPHELL_USE_IPP == 1
786  Ipp32u test;
787  ippsCmp_BN(src1, src2, &test);
788  return (test==IS_ZERO);
789 #elif MPHELL_USE_MBEDTLS == 1
790  return (mbedtls_mpi_cmp_mpi(src1, src2)==0);
791 #endif
792 }
793 
794 bool
795 number_isdiff_ui (number_srcptr src1, const block src2)
796 {
797 #if MPHELL_USE_GMP == 1
798  return (mpz_cmp_ui(src1, src2) != 0);
799 #elif (MPHELL_USE_IPP == 1 || MPHELL_USE_MBEDTLS == 1)
800  return (!number_isequal_ui(src1, src2));
801 #endif
802 }
803 
804 bool
805 number_isdiff (number_srcptr src1, number_srcptr src2)
806 {
807 #if MPHELL_USE_GMP == 1
808  return (mpz_cmp(src1, src2) != 0);
809 #elif (MPHELL_USE_IPP == 1 || MPHELL_USE_MBEDTLS == 1)
810  return (!number_isequal(src1, src2));
811 #endif
812 }
813 
814 bool
815 number_islower_ui (number_srcptr src1, const block src2)
816 {
817 #if MPHELL_USE_GMP == 1
818  return (mpz_cmp_ui(src1, src2) < 0);
819 #elif MPHELL_USE_IPP == 1
820  int len;
821  IppsBigNumSGN sgn;
822  Ipp32u * data;
823  ippsRef_BN(&sgn, &len, &data, src1);
824  if(sgn == IppsBigNumNEG)
825  {
826  return true;
827  }
828  if((len > 32) || (data[0]>=(Ipp32u)src2))
829  {
830  return false;
831  }
832  else
833  {
834  return true;
835  }
836 #elif MPHELL_USE_MBEDTLS == 1
837  return (mbedtls_mpi_cmp_int(src1, (mbedtls_mpi_sint)src2) < 0);
838 #endif
839 }
840 
841 bool
842 number_islower (number_srcptr src1, number_srcptr src2)
843 {
844 #if MPHELL_USE_GMP == 1
845  return (mpz_cmp(src1, src2) < 0);
846 #elif MPHELL_USE_IPP == 1
847  Ipp32u test;
848  ippsCmp_BN(src1, src2, &test);
849  return (test==LESS_THAN_ZERO);
850 #elif MPHELL_USE_MBEDTLS == 1
851  return (mbedtls_mpi_cmp_mpi(src1, src2)<0);
852 #endif
853 }
854 
855 bool
856 number_isgreater_ui (number_srcptr src1, const block src2)
857 {
858 #if MPHELL_USE_GMP == 1
859  return (mpz_cmp_ui(src1, src2) > 0);
860 #elif MPHELL_USE_IPP == 1
861  int len;
862  IppsBigNumSGN sgn;
863  Ipp32u * data;
864  ippsRef_BN(&sgn, &len, &data, src1);
865  if (len > 32)
866  {
867  return true;
868  }
869  if((sgn == IppsBigNumNEG) || (data[0]<=(Ipp32u)src2))
870  {
871  return false;
872  }
873  else
874  {
875  return true;
876  }
877 #elif MPHELL_USE_MBEDTLS == 1
878  return (mbedtls_mpi_cmp_int(src1, (mbedtls_mpi_sint)src2) > 0);
879 #endif
880 }
881 
882 bool
883 number_isgreater (number_srcptr src1, number_srcptr src2)
884 {
885 #if MPHELL_USE_GMP == 1
886  return (mpz_cmp(src1, src2) > 0);
887 #elif MPHELL_USE_IPP == 1
888  Ipp32u test;
889  ippsCmp_BN(src1, src2, &test);
890  return (test==GREATER_THAN_ZERO);
891 #elif MPHELL_USE_MBEDTLS == 1
892  return (mbedtls_mpi_cmp_mpi(src1, src2)>0);
893 #endif
894 
895 }
896 
897 bool
898 number_islowereq_ui (number_srcptr src1, const block src2)
899 {
900 #if MPHELL_USE_GMP == 1
901  return (mpz_cmp_ui(src1, src2) <= 0);
902 #elif MPHELL_USE_IPP == 1
903  return (number_islower_ui(src1, src2)==true || number_isequal_ui(src1, src2)==true);
904 #elif MPHELL_USE_MBEDTLS == 1
905  return (mbedtls_mpi_cmp_int(src1, (mbedtls_mpi_sint)src2) <= 0);
906 #endif
907 }
908 
909 bool
910 number_islowereq (number_srcptr src1, number_srcptr src2)
911 {
912 #if MPHELL_USE_GMP == 1
913  return (mpz_cmp(src1, src2) <= 0);
914 #elif MPHELL_USE_IPP == 1
915  return (number_islower(src1, src2)==true || number_isequal(src1, src2)==true);
916 #elif MPHELL_USE_MBEDTLS == 1
917  return (mbedtls_mpi_cmp_mpi(src1, src2)<=0);
918 #endif
919 }
920 
921 bool
922 number_isgreatereq_ui (number_srcptr src1, const block src2)
923 {
924 #if MPHELL_USE_GMP == 1
925  return (mpz_cmp_ui(src1, src2) >= 0);
926 #elif MPHELL_USE_IPP == 1
927  return (number_isgreater_ui(src1, src2)==true || number_isequal_ui(src1, src2)==true);
928 #elif MPHELL_USE_MBEDTLS == 1
929  return (mbedtls_mpi_cmp_int(src1, (mbedtls_mpi_sint)src2) >= 0);
930 #endif
931 }
932 
933 bool
934 number_isgreatereq (number_srcptr src1, number_srcptr src2)
935 {
936 #if MPHELL_USE_GMP == 1
937  return (mpz_cmp(src1, src2) >= 0);
938 #elif MPHELL_USE_IPP == 1
939  return (number_isgreater(src1, src2)==true || number_isequal(src1, src2)==true);
940 #elif MPHELL_USE_MBEDTLS == 1
941  return (mbedtls_mpi_cmp_mpi(src1, src2)>=0);
942 #endif
943 }
944 
945 int8_t
946 number_cmp_ui (number_srcptr src1, const block src2)
947 {
948 #if MPHELL_USE_GMP == 1
949  return mpz_cmp_ui(src1, src2);
950 #elif MPHELL_USE_IPP == 1
951  if(number_isgreater_ui(src1, src2))
952  {
953  return 1;
954  }
955  else if(number_islower_ui(src1, src2))
956  {
957  return -1;
958  }
959  return 0;
960 #elif MPHELL_USE_MBEDTLS == 1
961  return mbedtls_mpi_cmp_int(src1, (mbedtls_mpi_sint)src2);
962 #endif
963 }
964 
965 int8_t
966 number_cmp (number_srcptr src1, number_srcptr src2)
967 {
968 #if MPHELL_USE_GMP == 1
969  return mpz_cmp(src1, src2);
970 #elif MPHELL_USE_IPP == 1
971  Ipp32u test;
972  ippsCmp_BN(src1, src2, &test);
973  if(test==IS_ZERO)
974  {
975  return 0;
976  }
977  else if (test==GREATER_THAN_ZERO)
978  {
979  return 1;
980  }
981  else
982  {
983  return -1;
984  }
985 #elif MPHELL_USE_MBEDTLS == 1
986  return mbedtls_mpi_cmp_mpi(src1, src2);
987 #endif
988 }
989 
990 bool
991 number_iseven(number_srcptr src)
992 {
993 #if MPHELL_USE_GMP == 1
994  return !(LIMB(src)[0] & (block)1);
995 #elif MPHELL_USE_IPP == 1
996  Ipp32u * data;
997  ippsRef_BN(NULL, NULL, &data, src);
998  return !(data[0] & (block)1);
999 #elif MPHELL_USE_MBEDTLS == 1
1000  return !(src->p[0] & (block)1);
1001 #endif
1002 }
1003 
1004 bool
1005 number_isodd(number_srcptr src)
1006 {
1007 #if MPHELL_USE_GMP == 1
1008  return (LIMB(src)[0] & (block)1);
1009 #elif MPHELL_USE_IPP == 1
1010  Ipp32u * data;
1011  ippsRef_BN(NULL, NULL, &data, src);
1012  return (data[0] & (block)1);
1013 #elif MPHELL_USE_MBEDTLS == 1
1014  return (src->p[0] & (block)1);
1015 #endif
1016 }
1017 
1018 /************************************ LOGICAL ********************************/
1019 
1020 block
1021 number_and_ui (number_srcptr src1, const block src2, uint8_t stack)
1022 {
1023 #if MPHELL_USE_GMP == 1
1024  number t;
1025  number_tmp_alloc(&t, 1, stack);
1026  mpz_set_ui(t, src2);
1027  mpz_and(t, src1, t);
1028  block res = mpz_get_ui(t);
1029  number_tmp_free(&t, 1, stack);
1030  return res;
1031 #elif MPHELL_USE_IPP == 1
1032  Ipp32u * data;
1033  ippsRef_BN(NULL, NULL, &data, src1);
1034  return data[0] & (Ipp32u)src2;
1035 #elif MPHELL_USE_MBEDTLS == 1
1036  return (src1->p[0] & src2);
1037 #endif
1038 }
1039 
1040 void
1041 number_and (number_ptr dst, number_srcptr src1, number_srcptr src2)
1042 {
1043 #if MPHELL_USE_GMP == 1
1044  mpz_and(dst, src1, src2);
1045 #elif MPHELL_USE_IPP == 1
1046  Ipp32u * data1, * data2;
1047  int len1, len2, lenchunk1, lenchunk2;
1048  ippsRef_BN(NULL, &len1, &data1, src1);
1049  ippsRef_BN(NULL, &len2, &data2, src2);
1050  lenchunk1 = bits_to_nblock(len1);
1051  lenchunk2 = bits_to_nblock(len2);
1052  int i;
1053  int min;
1054  if(lenchunk1 < lenchunk2)
1055  {
1056  min = lenchunk1;
1057  }
1058  else
1059  {
1060  min = lenchunk2;
1061  }
1062  Ipp32u tab[min];
1063  for (i=0; i<min; i++)
1064  {
1065  tab[i] = data1[i] & data2[i];
1066  }
1067  ippsSet_BN(IppsBigNumPOS, min, tab, dst);
1068 #elif MPHELL_USE_MBEDTLS == 1
1069  int i;
1070  int min;
1071  if(src1->n < src2->n)
1072  {
1073  min = src1->n;
1074  }
1075  else
1076  {
1077  min = src2->n;
1078  }
1079  for (i=0; i<min; i++)
1080  {
1081  dst->p[i] = src1->p[i] & src2->p[i];
1082  }
1083  for (i=min; i<dst->n; i++)
1084  {
1085  dst->p[i] = 0;
1086  }
1087 #endif
1088 }
1089 
1090 void
1091 number_or_ui (number_ptr dst, number_srcptr src1, const block src2, uint8_t stack)
1092 {
1093 #if MPHELL_USE_GMP == 1
1094  number t;
1095  number_tmp_alloc(&t, 1, stack);
1096  mpz_set_ui(t, src2);
1097  mpz_ior(dst, src1, t);
1098  number_tmp_free(&t, 1, stack);
1099 #elif MPHELL_USE_IPP == 1
1100  number_copy(dst, src1);
1101  Ipp32u * data;
1102  ippsRef_BN(NULL, NULL, &data, dst);
1103  data[0] |= src2;
1104 #elif MPHELL_USE_MBEDTLS == 1
1105  number_copy(dst, src1);
1106  dst->p[0] |= src2;
1107 #endif
1108 }
1109 
1110 void
1111 number_or (number_ptr dst, number_srcptr src1, number_srcptr src2)
1112 {
1113 #if MPHELL_USE_GMP == 1
1114  mpz_ior(dst, src1, src2);
1115 #elif MPHELL_USE_IPP == 1
1116  int i;
1117  Ipp32u * data1, * data2;
1118  int len1, len2, lenchunk1, lenchunk2;
1119  ippsRef_BN(NULL, &len1, &data1, src1);
1120  ippsRef_BN(NULL, &len2, &data2, src2);
1121  lenchunk1 = bits_to_nblock(len1);
1122  lenchunk2 = bits_to_nblock(len2);
1123  if(lenchunk1 < lenchunk2)
1124  {
1125  Ipp32u tab[lenchunk2];
1126  for (i=0; i<lenchunk1; i++)
1127  {
1128  tab[i] = data1[i] | data2[i];
1129  }
1130  for(i=lenchunk1; i<lenchunk2; i++)
1131  {
1132  tab[i] = data2[i];
1133  }
1134  ippsSet_BN(IppsBigNumPOS, lenchunk2, tab, dst);
1135  }
1136  else
1137  {
1138  Ipp32u tab[lenchunk1];
1139  for (i=0; i<lenchunk2; i++)
1140  {
1141  tab[i] = data1[i] | data2[i];
1142  }
1143  for(i=lenchunk2; i<lenchunk1; i++)
1144  {
1145  tab[i] = data1[i];
1146  }
1147  ippsSet_BN(IppsBigNumPOS, lenchunk1, tab, dst);
1148  }
1149 #elif MPHELL_USE_MBEDTLS == 1
1150  int i;
1151  if(src1->n < src2->n)
1152  {
1153  for (i=0; i<src1->n; i++)
1154  {
1155  dst->p[i] = src1->p[i] | src2->p[i];
1156  }
1157  for(i=src1->n; i<src2->n; i++)
1158  {
1159  dst->p[i] = src2->p[i];
1160  }
1161  }
1162  else
1163  {
1164  for (i=0; i<src2->n; i++)
1165  {
1166  dst->p[i] = src1->p[i] | src2->p[i];
1167  }
1168  for(i=src2->n; i<src1->n; i++)
1169  {
1170  dst->p[i] = src1->p[i];
1171  }
1172  }
1173 #endif
1174 }
1175 
1176 void
1177 number_xor_ui (number_ptr dst, number_srcptr src1, const block src2, uint8_t stack)
1178 {
1179 #if MPHELL_USE_GMP == 1
1180  number t;
1181  number_tmp_alloc(&t, 1, stack);
1182  mpz_set_ui(t, src2);
1183  mpz_xor(dst, src1, t);
1184  number_tmp_free(&t, 1, stack);
1185 #elif MPHELL_USE_IPP == 1
1186  number_copy(dst, src1);
1187  Ipp32u * data;
1188  ippsRef_BN(NULL, NULL, &data, dst);
1189  data[0] ^= src2;
1190 #elif MPHELL_USE_MBEDTLS == 1
1191  number_copy(dst, src1);
1192  dst->p[0] ^= src2;
1193 #endif
1194 }
1195 
1196 void
1197 number_xor (number_ptr dst, number_srcptr src1, number_srcptr src2)
1198 {
1199 #if MPHELL_USE_GMP == 1
1200  mpz_xor(dst, src1, src2);
1201 #elif MPHELL_USE_IPP == 1
1202  int i;
1203  Ipp32u * data1, * data2;
1204  int len1, len2, lenchunk1, lenchunk2;
1205  ippsRef_BN(NULL, &len1, &data1, src1);
1206  ippsRef_BN(NULL, &len2, &data2, src2);
1207  lenchunk1 = bits_to_nblock(len1);
1208  lenchunk2 = bits_to_nblock(len2);
1209  if(lenchunk1 < lenchunk2)
1210  {
1211  Ipp32u tab[lenchunk2];
1212  for (i=0; i<lenchunk1; i++)
1213  {
1214  tab[i] = data1[i] ^ data2[i];
1215  }
1216  for(i=lenchunk1; i<lenchunk2; i++)
1217  {
1218  tab[i] = data2[i];
1219  }
1220  ippsSet_BN(IppsBigNumPOS, lenchunk2, tab, dst);
1221  }
1222  else
1223  {
1224  Ipp32u tab[lenchunk1];
1225  for (i=0; i<lenchunk2; i++)
1226  {
1227  tab[i] = data1[i] ^ data2[i];
1228  }
1229  for(i=lenchunk2; i<lenchunk1; i++)
1230  {
1231  tab[i] = data1[i];
1232  }
1233  ippsSet_BN(IppsBigNumPOS, lenchunk1, tab, dst);
1234  }
1235 #elif MPHELL_USE_MBEDTLS == 1
1236  int i;
1237  if(src1->n < src2->n)
1238  {
1239  for (i=0; i<src1->n; i++)
1240  {
1241  dst->p[i] = src1->p[i] ^ src2->p[i];
1242  }
1243  for(i=src1->n; i<src2->n; i++)
1244  {
1245  dst->p[i] = src2->p[i];
1246  }
1247  }
1248  else
1249  {
1250  for (i=0; i<src2->n; i++)
1251  {
1252  dst->p[i] = src1->p[i] ^ src2->p[i];
1253  }
1254  for(i=src2->n; i<src1->n; i++)
1255  {
1256  dst->p[i] = src1->p[i];
1257  }
1258  }
1259 #endif
1260 }
1261 
1262 void
1263 number_lshift (number_ptr dst, number_srcptr src, const uint16_t shift)
1264 {
1265 #if MPHELL_USE_GMP == 1
1266  mpz_mul_2exp(dst, src, shift);
1267 #elif MPHELL_USE_IPP == 1
1268  int q, r, len32;
1269  len32 = bits_to_nblock(shift);
1270  q = len32 - ((shift % 32)!=0);
1271  r = shift - q*32;
1272  int lenshift=len32+(r==0);
1273  Ipp32u data[lenshift];
1274  memset(data, 0, lenshift*4);
1275  data[lenshift-1] = (Ipp32u)1 << r;
1276  number tmp;
1277  number_init(&tmp, lenshift);
1278  ippsSet_BN(IppsBigNumPOS, lenshift, data, tmp);
1279  ippsMul_BN(src, tmp, dst);
1280  number_free(&tmp);
1281 #elif MPHELL_USE_MBEDTLS == 1
1282  number_copy(dst, src);
1283  mbedtls_mpi_shift_l(dst, shift);
1284 #endif
1285 }
1286 
1287 void
1288 number_rshift (number_ptr dst, number_srcptr src, const uint16_t shift)
1289 {
1290 #if MPHELL_USE_GMP == 1
1291  mpz_tdiv_q_2exp(dst, src, shift);
1292 #elif MPHELL_USE_IPP == 1
1293  int q, r, len32;
1294  len32 = bits_to_nblock(shift);
1295  q = len32 - ((shift % 32)!=0);
1296  r = shift - q*32;
1297  int lenshift=len32+(r==0);
1298  Ipp32u data[lenshift];
1299  memset(data, 0, lenshift*4);
1300  data[lenshift-1] = (Ipp32u)1 << r;
1301  number tmp;
1302  number_init(&tmp, lenshift);
1303  ippsSet_BN(IppsBigNumPOS, lenshift, data, tmp);
1304  number_div(dst, src, tmp);
1305  number_div(tmp, src, tmp);
1306  number_free(&tmp);
1307 #elif MPHELL_USE_MBEDTLS == 1
1308  number_copy(dst, src);
1309  mbedtls_mpi_shift_r(dst, shift);
1310 #endif
1311 }
1312 
1313 
1314 /********************************* ARITHMETIC ********************************/
1315 
1316 void
1317 number_add_ui (number_ptr dst, number_srcptr src1,
1318  const block src2)
1319 {
1320 #if MPHELL_USE_GMP == 1
1321  mpz_add_ui(dst, src1, src2);
1322 #elif MPHELL_USE_IPP == 1
1323  number tmp;
1324  number_init(&tmp, 1);
1325  number_set_ui(tmp, (Ipp32u)src2);
1326  ippsAdd_BN(src1, tmp, dst);
1327  number_free(&tmp);
1328 #elif MPHELL_USE_MBEDTLS == 1
1329  mbedtls_mpi_add_int(dst, src1, (mbedtls_mpi_sint)src2);
1330 #endif
1331 }
1332 
1333 void
1334 number_add (number_ptr dst, number_srcptr src1,
1335  number_srcptr src2)
1336 {
1337 #if MPHELL_USE_GMP == 1
1338  mpz_add(dst, src1, src2);
1339 #elif MPHELL_USE_IPP == 1
1340  ippsAdd_BN(src1, src2, dst);
1341 #elif MPHELL_USE_MBEDTLS == 1
1342  mbedtls_mpi_add_mpi(dst, src1, src2);
1343 #endif
1344 }
1345 
1346 void
1347 number_inc (number_ptr dst, number_srcptr src)
1348 {
1349  number_add_ui(dst, src, 1);
1350 }
1351 
1352 void
1353 number_sub_ui (number_ptr dst, number_srcptr src1,
1354  const block src2)
1355 {
1356 #if MPHELL_USE_GMP == 1
1357  mpz_sub_ui(dst, src1, src2);
1358 #elif MPHELL_USE_IPP == 1
1359  number tmp;
1360  number_init(&tmp, 1);
1361  number_set_ui(tmp, (Ipp32u)src2);
1362  ippsSub_BN(src1, tmp, dst);
1363  number_free(&tmp);
1364 #elif MPHELL_USE_MBEDTLS == 1
1365  mbedtls_mpi_sub_int(dst, src1, (mbedtls_mpi_sint)src2);
1366 #endif
1367 }
1368 
1369 void
1370 number_sub (number_ptr dst, number_srcptr src1,
1371  number_srcptr src2)
1372 {
1373 #if MPHELL_USE_GMP == 1
1374  mpz_sub(dst, src1, src2);
1375 #elif MPHELL_USE_IPP == 1
1376  ippsSub_BN(src1, src2, dst);
1377 #elif MPHELL_USE_MBEDTLS == 1
1378  mbedtls_mpi_sub_mpi(dst, src1, src2);
1379 #endif
1380 }
1381 
1382 void
1383 number_dec (number_ptr dst, number_srcptr src)
1384 {
1385  number_sub_ui(dst, src, 1);
1386 }
1387 
1388 void
1389 number_mul_ui (number_ptr dst, number_srcptr src1, const block src2)
1390 {
1391 #if MPHELL_USE_GMP == 1
1392  mpz_mul_ui(dst, src1, src2);
1393 #elif MPHELL_USE_IPP == 1
1394  number tmp;
1395  number_init(&tmp, 1);
1396  number_set_ui(tmp, (Ipp32u)src2);
1397  ippsMul_BN(src1, tmp, dst);
1398  number_free(&tmp);
1399 #elif MPHELL_USE_MBEDTLS == 1
1400  mbedtls_mpi_mul_int(dst, src1, (mbedtls_mpi_uint)src2);
1401 #endif
1402 }
1403 
1404 void
1405 number_addmul_ui (number_ptr dst, number_srcptr src1, const block src2)
1406 {
1407 #if MPHELL_USE_GMP == 1
1408  mpz_addmul_ui(dst, src1, src2);
1409 #elif MPHELL_USE_IPP == 1
1410  number tmp;
1411  number_init(&tmp, 1);
1412  number_set_ui(tmp, src2);
1413  ippsMAC_BN_I(src1, tmp, dst);
1414  number_free(&tmp);
1415 #elif MPHELL_USE_MBEDTLS == 1
1416  number tmp;
1417  number_init(&tmp, src1->n+1);
1418  number_mul_ui(tmp, src1, src2);
1419  number_add(dst, dst, tmp);
1420  number_free(&tmp);
1421 #endif
1422 }
1423 
1424 void
1425 number_mul (number_ptr dst, number_srcptr src1, number_srcptr src2)
1426 {
1427 #if MPHELL_USE_GMP == 1
1428  mpz_mul(dst, src1, src2);
1429 #elif MPHELL_USE_IPP == 1
1430  ippsMul_BN(src1, src2, dst);
1431 #elif MPHELL_USE_MBEDTLS == 1
1432  mbedtls_mpi_mul_mpi(dst, src1, src2);
1433 #endif
1434 }
1435 
1436 void number_mul_mod (number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr mod, uint8_t stack)
1437 {
1438 #if MPHELL_USE_GMP == 1
1439  uint8_t size = SIZ(src1)+SIZ(src2);
1440  number tmp;
1441  number_tmp_alloc(&tmp, size, stack);
1442  mpz_mul(tmp, src1, src2);
1443  mpz_mod(dst, tmp, mod);
1444  number_tmp_free(&tmp, size, stack);
1445 #elif MPHELL_USE_IPP == 1
1446  number mul;
1447  /* Get number of 32bits words src1 can store */
1448  int len1, len2, lenchunk1, lenchunk2;
1449  ippsRef_BN(NULL, &len1, NULL, src1);
1450  ippsRef_BN(NULL, &len2, NULL, src2);
1451  lenchunk1 = bits_to_nblock(len1);
1452  lenchunk2 = bits_to_nblock(len2);
1453  number_tmp_alloc(&mul, lenchunk1+lenchunk2, stack);
1454  ippsMul_BN(src1, src2, mul);
1455  ippsMod_BN(mul, mod, dst);
1456  number_tmp_free(&mul, lenchunk1+lenchunk2, stack);
1457 #elif MPHELL_USE_MBEDTLS == 1
1458  uint8_t size = src1->n+src2->n;
1459  number tmp;
1460  number_tmp_alloc(&tmp, size, stack);
1461  mbedtls_mpi_mul_mpi(tmp, src1, src2);
1462  mbedtls_mpi_mod_mpi(dst, tmp, mod);
1463  number_tmp_free(&tmp, size, stack);
1464 #endif
1465 }
1466 
1467 void
1468 number_addmul (number_ptr dst, number_srcptr src1, number_srcptr src2)
1469 {
1470 #if MPHELL_USE_GMP == 1
1471  mpz_addmul(dst, src1, src2);
1472 #elif MPHELL_USE_IPP == 1
1473  ippsMAC_BN_I(src1, src2, dst);
1474 #elif MPHELL_USE_MBEDTLS == 1
1475  number tmp;
1476  number_init(&tmp, src1->n+src2->n);
1477  number_mul(tmp, src1, src2);
1478  number_add(dst, dst, tmp);
1479  number_free(&tmp);
1480 #endif
1481 }
1482 
1483 void
1484 number_pow (number_ptr dst, number_srcptr src1, number_srcptr src2, uint8_t stack)
1485 {
1486 #if MPHELL_USE_GMP == 1
1487  mpz_pow_ui(dst, src1, mpz_get_ui(src2));
1488 #elif MPHELL_USE_IPP == 1
1489  int len1, len2, lenchunk1, lenchunk2;
1490  ippsRef_BN(NULL, &len1, NULL, src1);
1491  ippsRef_BN(NULL, &len2, NULL, src2);
1492  lenchunk1 = bits_to_nblock(len1);
1493  lenchunk2 = bits_to_nblock(len2);
1494 
1495  number tmp;
1496  number_tmp_alloc(&tmp, lenchunk1*len2, stack);
1497  number_copy(tmp, src1);
1498 
1499  number m;
1500  number_tmp_alloc(&m, lenchunk2, stack);
1501  number_copy(m, src2);
1502 
1503  number_set_ui(dst, 1);
1504  while (!number_iszero(m))
1505  {
1506  if (number_isodd(m))
1507  {
1508  number_mul(dst, dst, tmp);
1509  }
1510  number_sqr(tmp, tmp);
1511  number_rshift(m, m, 1);
1512  }
1513  number_tmp_free(&tmp, lenchunk1*len2, stack);
1514  number_tmp_free(&m, lenchunk2, stack);
1515 #elif MPHELL_USE_MBEDTLS == 1
1516  int16_t len2 = number_log2(src2);
1517  number tmp;
1518  number_tmp_alloc(&tmp, src1->n*len2, stack);
1519  number_copy(tmp, src1);
1520 
1521  number m;
1522  number_tmp_alloc(&m, src2->n, stack);
1523  number_copy(m, src2);
1524 
1525  number_set_ui(dst, 1);
1526  while (!number_iszero(m))
1527  {
1528  if (number_isodd(m))
1529  {
1530  number_mul(dst, dst, tmp);
1531  }
1532  number_sqr(tmp, tmp);
1533  number_rshift(m, m, 1);
1534  }
1535  number_tmp_free(&tmp, src1->n*len2, stack);
1536  number_tmp_free(&m, src2->n, stack);
1537 #endif
1538 }
1539 
1540 void
1541 number_powm (number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr mod, uint8_t stack)
1542 {
1543 #if MPHELL_USE_GMP == 1
1544  mpz_powm(dst, src1, src2, mod);
1545 #elif MPHELL_USE_IPP == 1
1546  int i,len1, len2, lenchunk1;
1547  char *m;
1548  ippsRef_BN(NULL, &len1, NULL, mod);
1549  lenchunk1 = bits_to_nblock(len1);
1550 
1551  number tmp;
1552  number_tmp_alloc(&tmp, lenchunk1, stack);
1553  number_copy(tmp, src1);
1554 
1555  number_str(&m, src2, 2);
1556  len2=strlen(m);
1557  number_set_ui(dst, 1);
1558  for(i=len2-1; i>=0; i--)
1559  {
1560  if(m[i]=='1')
1561  {
1562  number_mul_mod(dst, dst, tmp, mod, stack);
1563  }
1564  number_mul_mod(tmp, tmp, tmp, mod, stack);
1565  }
1566  free(m);
1567  number_tmp_free(&tmp, lenchunk1, stack);
1568 #elif MPHELL_USE_MBEDTLS == 1
1569  if(number_isodd(mod))
1570  {
1571  mbedtls_mpi_exp_mod(dst, src1, src2, mod, NULL);
1572  }
1573  else
1574  {
1575  int i;
1576  char *m;
1577 
1578  number tmp;
1579  number_tmp_alloc(&tmp, mod->n, stack);
1580  number_copy(tmp, src1);
1581  number_str(&m, src2, 2);
1582  number_set_ui(dst, 1);
1583  for(i=strlen(m)-1; i>=0; i--)
1584  {
1585  if(m[i]=='1')
1586  {
1587  number_mul_mod(dst, dst, tmp, mod, stack);
1588  }
1589  number_mul_mod(tmp, tmp, tmp, mod, stack);
1590  }
1591  free(m);
1592  number_tmp_free(&tmp, mod->n, stack);
1593  }
1594 #endif
1595 }
1596 
1597 void
1598 number_powm_ui (number_ptr dst, number_srcptr src1, const block src2, number_srcptr mod, uint8_t stack)
1599 {
1600 #if MPHELL_USE_GMP == 1
1601  mpz_powm_ui(dst, src1, src2, mod);
1602 #elif MPHELL_USE_IPP == 1
1603  block m = src2;
1604  int len1, lenchunk1;
1605  ippsRef_BN(NULL, &len1, NULL, mod);
1606  lenchunk1 = bits_to_nblock(len1);
1607  number tmp;
1608  number_tmp_alloc(&tmp, lenchunk1, stack);
1609  number_copy(tmp, src1);
1610  number_set_ui(dst, 1);
1611  while (m != (block)0)
1612  {
1613  if (m & (block)1)
1614  {
1615  number_mul_mod(dst, dst, tmp, mod, stack);
1616  }
1617  number_mul_mod(tmp, tmp, tmp, mod, stack);
1618  m >>= 1;
1619  }
1620  number_tmp_free(&tmp, lenchunk1, stack);
1621 #elif MPHELL_USE_MBEDTLS == 1
1622  if(number_isodd(mod))
1623  {
1624  mbedtls_mpi B;
1625  mbedtls_mpi_uint p[1];
1626 
1627  p[0] = src2;
1628  B.s = 1;
1629  B.n = 1;
1630  B.p = p;
1631  mbedtls_mpi_exp_mod(dst, src1, &B, mod, NULL);
1632  }
1633  else
1634  {
1635  block m = src2;
1636  number tmp;
1637  number_tmp_alloc(&tmp, mod->n, stack);
1638  number_copy(tmp, src1);
1639  number_set_ui(dst, 1);
1640  while (m != (block)0)
1641  {
1642  if (m & (block)1)
1643  {
1644  number_mul_mod(dst, dst, tmp, mod, stack);
1645  }
1646  number_mul_mod(tmp, tmp, tmp, mod, stack);
1647  m >>= 1;
1648  }
1649  number_tmp_free(&tmp, mod->n, stack);
1650  }
1651 #endif
1652 }
1653 
1654 void
1655 number_sqr (number_ptr dst, number_srcptr src)
1656 {
1657 #if MPHELL_USE_GMP == 1
1658  mpz_mul(dst, src, src);
1659 #elif MPHELL_USE_IPP == 1
1660  ippsMul_BN(src, src, dst);
1661 #elif MPHELL_USE_MBEDTLS == 1
1662  mbedtls_mpi_mul_mpi(dst, src, src);
1663 #endif
1664 }
1665 
1666 void
1667 number_divmod_ui (number_ptr q, block *r, number_srcptr src1,
1668  const block src2)
1669 {
1670 #if MPHELL_USE_GMP == 1
1671  *r = mpz_fdiv_q_ui(q, src1, src2);
1672 #elif MPHELL_USE_IPP == 1
1673  number rst;
1674  number_init(&rst, 1);
1675  number b;
1676  number_init(&b, 1);
1677  number_set_ui(b, src2);
1678  ippsDiv_BN(src1, b, q, rst);
1679  Ipp32u * data;
1680  ippsRef_BN(NULL, NULL, &data, rst);
1681  *r = data[0];
1682  number_free(&rst);
1683  number_free(&b);
1684 #elif MPHELL_USE_MBEDTLS == 1
1685  mbedtls_mpi B;
1686  mbedtls_mpi_uint p[1];
1687  B.s = 1;
1688  B.n = 1;
1689  B.p = p;
1690  mbedtls_mpi_div_int(q, &B, src1, (mbedtls_mpi_sint)src2);
1691  *r = B.p[0];
1692 #endif
1693 }
1694 
1695 void
1696 number_divmod (number_ptr q, number_ptr r, number_srcptr src1,
1697  number_srcptr src2)
1698 {
1699 #if MPHELL_USE_GMP == 1
1700  mpz_divmod(q, r, src1, src2);
1701 #elif MPHELL_USE_IPP == 1
1702  ippsDiv_BN(src1, src2, q, r);
1703 #elif MPHELL_USE_MBEDTLS == 1
1704  mbedtls_mpi_div_mpi(q, r, src1, src2);
1705 #endif
1706 }
1707 
1708 void
1709 number_div_ui (number_ptr dst, number_srcptr src1, const block src2)
1710 {
1711 #if MPHELL_USE_GMP == 1
1712  mpz_fdiv_q_ui(dst, src1, src2);
1713 #elif MPHELL_USE_IPP == 1
1714  number rst;
1715  number_init(&rst, 1);
1716  number b;
1717  number_init(&b, 1);
1718  number_set_ui(b, src2);
1719  ippsDiv_BN(src1, b, dst, rst);
1720  number_free(&rst);
1721  number_free(&b);
1722 #elif MPHELL_USE_MBEDTLS == 1
1723  mbedtls_mpi B;
1724  mbedtls_mpi_uint p[1];
1725  B.s = 1;
1726  B.n = 1;
1727  B.p = p;
1728  mbedtls_mpi_div_int(dst, &B, src1, (mbedtls_mpi_sint)src2);
1729 #endif
1730 }
1731 
1732 void
1733 number_div (number_ptr dst, number_srcptr src1, number_srcptr src2)
1734 {
1735 #if MPHELL_USE_GMP == 1
1736  mpz_div(dst, src1, src2);
1737 #elif MPHELL_USE_IPP == 1
1738  number rst;
1739  int len, lenchunk;
1740  ippsRef_BN(NULL, &len, NULL, src2);
1741  lenchunk = bits_to_nblock(len);
1742  number_init(&rst, lenchunk);
1743  ippsDiv_BN(src1, src2, dst, rst);
1744  number_free(&rst);
1745 #elif MPHELL_USE_MBEDTLS == 1
1746  mbedtls_mpi_div_mpi(dst, NULL, src1, src2);
1747 #endif
1748 }
1749 
1750 void
1751 number_mod_ui (block *dst, number_srcptr src1, const block src2)
1752 {
1753 #if MPHELL_USE_GMP == 1
1754  *dst = mpz_fdiv_ui(src1, (block)src2);
1755 #elif MPHELL_USE_IPP == 1
1756  number b, d;
1757  number_init(&b, 1);
1758  number_init(&d, 1);
1759  number_set_ui(b, src2);
1760  ippsMod_BN(src1, b, d);
1761  Ipp32u * data;
1762  ippsRef_BN(NULL, NULL, &data, d);
1763  *dst = data[0];
1764  number_free(&b);
1765  number_free(&d);
1766 #elif MPHELL_USE_MBEDTLS == 1
1767  mbedtls_mpi B;
1768  mbedtls_mpi_uint p[1];
1769  B.s = 1;
1770  B.n = 1;
1771  B.p = p;
1772  mbedtls_mpi C;
1773  mbedtls_mpi_uint q[1];
1774  C.s = 1;
1775  C.n = 1;
1776  C.p = q;
1777  C.p[0] = src2;
1778  mbedtls_mpi_mod_mpi(&B, src1, &C);
1779  *dst = B.p[0];
1780 #endif
1781 }
1782 
1783 
1784 void
1785 number_mod (number_ptr dst, number_srcptr src1, number_srcptr src2)
1786 {
1787 #if MPHELL_USE_GMP == 1
1788  mpz_mod(dst, src1, src2);
1789 #elif MPHELL_USE_IPP == 1
1790  ippsMod_BN(src1, src2, dst);
1791 #elif MPHELL_USE_MBEDTLS == 1
1792  mbedtls_mpi_mod_mpi(dst, src1, src2);
1793 #endif
1794 }
1795 
1796 void
1797 number_invmod (number_ptr dst, number_srcptr src1, number_srcptr src2)
1798 {
1799  MPHELL_ASSERT_ALWAYS(number_iszero(src1) == false , "number_invmod : src1 == 0");
1800  if(number_isequal_ui(src1, 1))
1801  {
1802  number_copy(dst, src1);
1803  return;
1804  }
1805 #if MPHELL_USE_GMP == 1
1806  mpz_invert(dst, src1, src2);
1807 #elif MPHELL_USE_IPP == 1
1808  if(dst == src1)
1809  {
1810  int len1, lenchunk1;
1811  ippsRef_BN(NULL, &len1, NULL, src1);
1812  lenchunk1 = bits_to_nblock(len1);
1813  number tmp;
1814  number_init(&tmp, lenchunk1);
1815  number_copy(tmp, src1);
1816  IppStatus st = ippsModInv_BN(tmp, src2, dst);
1817  if(st != ippStsNoErr)
1818  {
1819  printf("Error ippsModInv_BN: %s\n", ippcpGetStatusString(st));
1820  }
1821  number_free(&tmp);
1822  }
1823  else if(dst == src2)
1824  {
1825  int len2, lenchunk2;
1826  ippsRef_BN(NULL, &len2, NULL, src2);
1827  lenchunk2 = bits_to_nblock(len2);
1828  number tmp;
1829  number_init(&tmp, lenchunk2);
1830  number_copy(tmp, src2);
1831  IppStatus st = ippsModInv_BN(src1, tmp, dst);
1832  if(st != ippStsNoErr)
1833  {
1834  printf("Error ippsModInv_BN: %s\n", ippcpGetStatusString(st));
1835  }
1836  number_free(&tmp);
1837  }
1838  else
1839  {
1840  IppStatus st = ippsModInv_BN(src1, src2, dst);
1841  if(st != ippStsNoErr)
1842  {
1843  printf("Error ippsModInv_BN: %s\n", ippcpGetStatusString(st));
1844  }
1845  }
1846 #elif MPHELL_USE_MBEDTLS == 1
1847  mbedtls_mpi_inv_mod(dst, src1, src2);
1848 #endif
1849 }
1850 
1851 void number_inv_mod_basis(block * dst, const block src)
1852 {
1853 #if MPHELL_USE_GMP == 1
1854  /* minus_src = -src */
1855  mpz_t minus_src;
1856  mpz_init(minus_src);
1857  mpz_set_ui(minus_src, src);
1858  mpz_neg(minus_src, minus_src);
1859 
1860  /* base = 2^32 or 2^64 according to the block size */
1861  mpz_t one;
1862  mpz_t base;
1863  mpz_init(one);
1864  mpz_init(base);
1865  mpz_set_ui(one, 1);
1866  mpz_mul_2exp(base, one, BLOCK_SIZE);
1867 
1868  /* dst ; dst * (-src) = 1 mod base */
1869  mpz_t res;
1870  mpz_init(res);
1871  mpz_invert(res, minus_src, base);
1872  *dst = mpz_get_ui(res);
1873 
1874  /* Free */
1875  mpz_clear(minus_src);
1876  mpz_clear(one);
1877  mpz_clear(base);
1878  mpz_clear(res);
1879 #elif MPHELL_USE_IPP == 1
1880  /* Not implemented */
1881 #elif MPHELL_USE_MBEDTLS == 1
1882  mbedtls_mpi_uint x, m0 = src;
1883  unsigned int i;
1884 
1885  x = m0;
1886  x += ( ( m0 + 2 ) & 4 ) << 1;
1887 
1888  for( i = sizeof(mbedtls_mpi_uint)<<3; i >= 8; i /= 2 )
1889  x *= ( 2 - ( m0 * x ) );
1890 
1891  *dst = ~x + 1;
1892 #endif
1893 }
1894 
1895 
1896 #if MPHELL_USE_GMP == 1
1897 
1898 void
1899 redcify(number_ptr dst, number_srcptr src, number_srcptr p, uint8_t stack)
1900 {
1901  number tp;
1902  uint8_t n = SIZ(p)+SIZ(src);
1903  number_tmp_alloc(&tp, n, stack);
1904  mpz_mul_2exp(tp, src, SIZ(p)*BLOCK_SIZE); /* a simple multiplication by 2^(n*BLOCK_SIZE)=R */
1905  mpz_tdiv_r (dst, tp, p);
1906  number_tmp_free(&tp, n, stack);
1907 }
1908 
1915 void
1916 gmp_rshift1(mpz_t dst, uint8_t size)
1917 {
1918  uint8_t i;
1919  for (i = 0; i < size-1; i++)
1920  {
1921  LIMB(dst)[i]=LIMB(dst)[i+1];
1922  }
1923  LIMB(dst)[size-1]= 0;
1924  SIZ(dst) = size-1;
1925 }
1926 
1936 mp_size_t
1937 gmp_redc_1 (mp_ptr rp, mp_ptr up, mp_srcptr mp, mp_size_t n, mp_limb_t invm)
1938 {
1939  mp_size_t i, j, rs;
1940  mp_limb_t cy;
1941 
1942  for (j = n - 1; j >= 0; j--)
1943  {
1944  cy = mpn_addmul_1 (up, mp, n, (up[0] * invm) & GMP_NUMB_MASK);
1945  MPHELL_ASSERT (up[0] == 0, "mphell_redc_1 : up[0] == 0");
1946  up[0] = cy;
1947  up++;
1948  }
1949  cy = mpn_add_n (rp, up, up - n, n);
1950 
1951  if (cy != 0)
1952  {
1953  mpn_sub_n (rp, rp, mp, n);
1954  }
1955  if(mpn_cmp(rp, mp, n)>0)
1956  {
1957  mpn_sub_n (rp, rp, mp, n);
1958  }
1959 
1960  /* Adjust size */
1961  rs = n;
1962  for(i=n-1; i>=0; i--)
1963  {
1964  if(rp[i]==0)
1965  {
1966  rs--;
1967  }
1968  else
1969  {
1970  break;
1971  }
1972  }
1973  return rs;
1974 }
1975 
1985 void
1986 gmp_mred_full(number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr p,
1987  const block invp, uint8_t stack)
1988 {
1989  uint8_t n = SIZ(p);
1990 
1991  number tmp;
1992  number_tmp_alloc(&tmp, 2*n, stack);
1993  mpn_mul_n(LIMB(tmp), LIMB(src1), LIMB(src2), n);
1994  SIZ(dst)=gmp_redc_1(LIMB(dst), LIMB(tmp), LIMB(p), n, invp);
1995  number_tmp_free(&tmp, 2*n, stack);
1996 }
1997 
2007 void
2008 gmp_mred_block(number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr p,
2009  const block invp, uint8_t stack)
2010 {
2011  uint8_t n = SIZ(p);
2012  uint8_t n1 = SIZ(src1);
2013 
2014  if(number_iszero(src1) || number_iszero(src2))
2015  {
2016  number_set_ui(dst, (block)0);
2017  return;
2018  }
2019 
2020  number tmp;
2021  number_tmp_alloc(&tmp, n, stack);
2022  mpz_set_ui(tmp, 0);
2023 
2024  mp_limb_t *res = LIMB(tmp);
2025  mp_limb_t m, carry, a;
2026  uint8_t i;
2027 
2028  memset(res, 0, n*BLOCK_SIZE);
2029 
2030  for (i = 0; i < n1; i++)
2031  {
2032  /* m = (res[0] + y[0]*x[i])*invp */
2033  m = (res[0] + (LIMB(src1)[i] * LIMB(src2)[0])) * invp;
2034 
2035 
2036  /* res += y*x[i] + p*m */
2037  carry = mpn_addmul_1 (res, LIMB(src2), SIZ(src2), LIMB(src1)[i]);
2038 
2039  if((SIZ(src2) < n) && (carry > 0))
2040  {
2041  carry = mpn_add_1 (res + SIZ(src2), res + SIZ(src2), n - SIZ(src2), carry);
2042  }
2043 
2044  a = mpn_addmul_1 (res, LIMB(p), n, m);
2045  gmp_rshift1(tmp, n);
2046 
2047  res[n - 1] = carry + a;
2048  /* res >=p ? res -= p */
2049  if ((res[n - 1] < a) || (res[n - 1] < carry))
2050  {
2051  mpn_sub (res, res, n, LIMB(p), n);
2052  }
2053  else if (mpn_cmp(res, LIMB(p), n)>=0)
2054  {
2055  mpn_sub (res, res, n, LIMB(p), n);
2056  }
2057  }
2058  for (i = n1; i < n; i++)
2059  {
2060  /* m = res[0] * invp */
2061  m = res[0] * invp;
2062 
2063  /* res += p*m */
2064  a = mpn_addmul_1 (res, LIMB(p), n, m);
2065 
2066  /* res >>= BLOCK_SIZE */
2067  gmp_rshift1(tmp, n);
2068 
2069  res[n - 1] = a;
2070 
2071  /* res >=p ? res -= p */
2072  if (mpn_cmp(res, LIMB(p), n)>=0)
2073  {
2074  mpn_sub (res, res, n, LIMB(p), n);
2075  }
2076  }
2077  /* Adjust size */
2078  SIZ(tmp) = n;
2079  for(i=n-1; i>=0; i--)
2080  {
2081  if(res[i]==0)
2082  {
2083  SIZ(tmp)--;
2084  }
2085  else
2086  {
2087  break;
2088  }
2089  }
2090  mpn_copyi(LIMB(dst), res, SIZ(tmp));
2091  SIZ(dst) = SIZ(tmp);
2092  number_tmp_free(&tmp, n, stack);
2093 }
2094 #elif MPHELL_USE_IPP == 1
2095  /* Not implemented */
2096 
2097 #elif MPHELL_USE_MBEDTLS == 1
2098  /* Not implemented */
2099 
2100 void
2101 redcify(number_ptr dst, number_srcptr src, number_srcptr p, uint8_t stack)
2102 {
2103  number tp;
2104  uint8_t n = p->n+src->n;
2105  number_tmp_alloc(&tp, n, stack);
2106  number_lshift(tp, src, p->n*BLOCK_SIZE); /* a simple multiplication by 2^(n*BLOCK_SIZE)=R */
2107  number_mod (dst, tp, p);
2108  number_tmp_free(&tp, n, stack);
2109 }
2110 
2111 /*
2112  * Helper for mbedtls_mpi multiplication
2113  */
2114 static
2115 #if defined(__APPLE__) && defined(__arm__)
2116 /*
2117  * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
2118  * appears to need this to prevent bad ARM code generation at -O3.
2119  */
2120 __attribute__ ((noinline))
2121 #endif
2122 void mpi_mul_hlp_mphell( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
2123 {
2124  mbedtls_mpi_uint c = 0, t = 0;
2125 
2126 #if defined(MULADDC_HUIT)
2127  for( ; i >= 8; i -= 8 )
2128  {
2129  MULADDC_INIT
2130  MULADDC_HUIT
2131  MULADDC_STOP
2132  }
2133 
2134  for( ; i > 0; i-- )
2135  {
2136  MULADDC_INIT
2137  MULADDC_CORE
2138  MULADDC_STOP
2139  }
2140 #else /* MULADDC_HUIT */
2141  for( ; i >= 16; i -= 16 )
2142  {
2143  MULADDC_INIT
2144  MULADDC_CORE MULADDC_CORE
2145  MULADDC_CORE MULADDC_CORE
2146  MULADDC_CORE MULADDC_CORE
2147  MULADDC_CORE MULADDC_CORE
2148 
2149  MULADDC_CORE MULADDC_CORE
2150  MULADDC_CORE MULADDC_CORE
2151  MULADDC_CORE MULADDC_CORE
2152  MULADDC_CORE MULADDC_CORE
2153  MULADDC_STOP
2154  }
2155 
2156  for( ; i >= 8; i -= 8 )
2157  {
2158  MULADDC_INIT
2159  MULADDC_CORE MULADDC_CORE
2160  MULADDC_CORE MULADDC_CORE
2161 
2162  MULADDC_CORE MULADDC_CORE
2163  MULADDC_CORE MULADDC_CORE
2164  MULADDC_STOP
2165  }
2166 
2167  for( ; i > 0; i-- )
2168  {
2169  MULADDC_INIT
2170  MULADDC_CORE
2171  MULADDC_STOP
2172  }
2173 #endif /* MULADDC_HUIT */
2174 
2175  t++;
2176 
2177  do {
2178  *d += c; c = ( *d < c ); d++;
2179  }
2180  while( c != 0 );
2181 }
2182 
2183 /*
2184  * Helper for mbedtls_mpi subtraction
2185  */
2186 static void mpi_sub_hlp_mphell( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
2187 {
2188  size_t i;
2189  mbedtls_mpi_uint c, z;
2190 
2191  for( i = c = 0; i < n; i++, s++, d++ )
2192  {
2193  z = ( *d < c ); *d -= c;
2194  c = ( *d < *s ) + z; *d -= *s;
2195  }
2196 
2197  while( c != 0 )
2198  {
2199  z = ( *d < c ); *d -= c;
2200  c = z; d++;
2201  }
2202 }
2203 
2204 void
2205 mpi_montmul_mphell(mbedtls_mpi *Dst, const mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
2206 {
2207  size_t i, n, m;
2208  mbedtls_mpi_uint u0, u1, *d;
2209 
2210  memset( T->p, 0, T->n * BYTES_PER_LIMB );
2211 
2212  d = T->p;
2213  n = N->n;
2214  m = ( B->n < n ) ? B->n : n;
2215 
2216  for( i = 0; i < n; i++ )
2217  {
2218  /*
2219  * T = (T + u0*B + u1*N) / 2^biL
2220  */
2221  u0 = A->p[i];
2222  u1 = ( d[0] + u0 * B->p[0] ) * mm;
2223 
2224  mpi_mul_hlp_mphell( m, B->p, d, u0 );
2225  mpi_mul_hlp_mphell( n, N->p, d, u1 );
2226 
2227  *d++ = u0; d[n + 1] = 0;
2228  }
2229 
2230  memcpy( Dst->p, d, ( n + 1 ) * BYTES_PER_LIMB );
2231 
2232  if( mbedtls_mpi_cmp_abs( Dst, N ) >= 0 )
2233  {
2234  mpi_sub_hlp_mphell( n, N->p, Dst->p );
2235  }
2236 }
2237 #endif
2238 
2239 
2240 void
2241 number_mul_montgomery(number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr p, const block invp, uint8_t stack)
2242 {
2243 #if MPHELL_USE_GMP == 1
2244  MPHELL_ASSERT(SIZ(src1) >= 0, "number_mul_montgomery : invalid size for src1");
2245  MPHELL_ASSERT(SIZ(src2) >= 0, "number_mul_montgomery : invalid size for src2");
2246  MPHELL_ASSERT(SIZ(p) >= 1, "number_mul_montgomery : invalid size for p");
2247  MPHELL_ASSERT(ALLOC_SIZ(dst) >= 1, "number_mul_montgomery : invalid size for dst");
2248  uint8_t n = SIZ(p);
2249  if((SIZ(src1) == n) && (SIZ(src2) == n))
2250  {
2251  gmp_mred_full(dst, src1, src2, p, invp, stack);
2252  }
2253  else
2254  {
2255  gmp_mred_block(dst, src1, src2, p, invp, stack);
2256  }
2257 #elif MPHELL_USE_IPP == 1
2258  /* Not implemented */
2259 #elif MPHELL_USE_MBEDTLS == 1
2260  number tmp;
2261  number_tmp_alloc(&tmp, p->n+2, stack);
2262  mpi_montmul_mphell(dst, src1, src2, p, invp, tmp );
2263  number_tmp_free(&tmp, p->n+2, stack);
2264 #endif
2265 }
2266 
2267 void
2268 number_mul_montgomery_block(number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr p, const block invp, uint8_t stack)
2269 {
2270 #if MPHELL_USE_GMP == 1
2271  MPHELL_ASSERT(SIZ(src1) >= 0, "number_mul_montgomery : invalid size for src1");
2272  MPHELL_ASSERT(SIZ(src2) >= 0, "number_mul_montgomery : invalid size for src2");
2273  MPHELL_ASSERT(SIZ(p) >= 1, "number_mul_montgomery : invalid size for p");
2274  MPHELL_ASSERT(ALLOC_SIZ(dst) >= 1, "number_mul_montgomery : invalid size for dst");
2275  gmp_mred_block(dst, src1, src2, p, invp, stack);
2276 #elif MPHELL_USE_IPP == 1
2277  /* Not implemented */
2278 #elif MPHELL_USE_MBEDTLS == 1
2279  /* Not implemented */
2280  number tmp;
2281  number_tmp_alloc(&tmp, p->n+2, stack);
2282  mpi_montmul_mphell(dst, src1, src2, p, invp, tmp );
2283  number_tmp_free(&tmp, p->n+2, stack);
2284 #endif
2285 }
2286 
2287 void
2288 number_inv_montgomery(number_ptr dst, number_srcptr src, number_srcptr p, const block invp,
2289  number_srcptr R2, number_srcptr one, uint8_t stack)
2290 {
2291 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
2292  MPHELL_ASSERT(SIZ(src) >= 1, "u_invmod : invalid size for src");
2293  MPHELL_ASSERT(SIZ(R2) >= 1, "u_invmod : invalid size for R2");
2294  MPHELL_ASSERT(SIZ(p) >= 1, "u_invmod : invalid size for p");
2295  MPHELL_ASSERT(SIZ(one) >= 1, "u_invmod : invalid size for one");
2296  MPHELL_ASSERT(ALLOC_SIZ(dst) >= 1, "u_invmod : invalid size for dst");
2297 
2298  uint8_t n = SIZ(p);
2299 
2300  MPHELL_ASSERT_ALWAYS(number_iszero(src)==false, "u_invmod : inversion of 0");
2301 
2302  if(number_isequal(src, one))
2303  {
2304  number_copy(dst, one);
2305  return;
2306  }
2307 
2308  number t, s, r, v;
2309  number_tmp_alloc(&t, n, stack);
2310  number_tmp_alloc(&s, n, stack);
2311  number_tmp_alloc(&r, n, stack);
2312  number_tmp_alloc(&v, n+1, stack);
2313 
2314  number_copy(r, src); /* r <- src */
2315  number_copy(t, p); /* t <- p */
2316  number_set_ui(s, 1); /* s <- 1 */
2317  number_set_ui(v, 0); /* v <- 0 */
2318 
2319  block k;
2320  uint8_t c = 0;
2321  k = 0;
2322 
2323  while(number_isdiff_ui(r,0))
2324  {
2325  if(!(LIMB(t)[0] & 1)) /* If tn != 1 */
2326  {
2327  number_rshift(t, t, 1); /* t >> 1 */
2328  number_lshift(s, s, 1); /* s = 2 * s */
2329  }
2330  else if(!(LIMB(r)[0] & 1)) /* If rn != 1 */
2331  {
2332  number_rshift(r, r, 1); /* r >> 1 */
2333  number_lshift(v, v, 1); /* v = 2 * v */
2334  }
2335  else if(number_isgreater(t,r))
2336  {
2337  number_sub(t, t, r);
2338  number_rshift(t, t, 1); /* t >> 1 */
2339  number_add(v, v, s);
2340  number_lshift(s, s, 1); /* s = 2 * s */
2341  }
2342  else
2343  {
2344  number_sub(r, r, t);
2345  number_rshift(r, r, 1); /* r >> 1 */
2346  number_add(s, v, s);
2347  number_lshift(v, v, 1); /* v = 2 * v */
2348  }
2349  k++;
2350  }
2351  if(c)
2352  {
2353  number_sub(v, v, p);
2354  }
2355  if(number_isgreatereq(v, p))
2356  {
2357  number_sub(v, v, p);
2358  }
2359  number_sub(v, p, v);
2360 
2361  if(k <= (BLOCK_SIZE * n))
2362  {
2363  number_mul_montgomery(v, v, R2, p, invp, stack);
2364  k += BLOCK_SIZE * n;
2365  }
2366 
2367  number_mul_montgomery(v, v, R2, p, invp, stack);
2368  number_set_ui(s, 1);
2369 
2370  number_lshift(s, s, (2 * BLOCK_SIZE * n) - k);
2371  number_mul_montgomery(dst, v, s, p, invp, stack);
2372 
2373  number_tmp_free(&t, n, stack);
2374  number_tmp_free(&s, n, stack);
2375  number_tmp_free(&r, n, stack);
2376  number_tmp_free(&v, n+1, stack);
2377 
2378 #elif MPHELL_USE_IPP == 1
2379  /* Not implemented */
2380 #endif
2381 }
2382 
2383 int8_t
2384 number_legendre (number_srcptr src1, number_srcptr src2, uint8_t stack)
2385 {
2386 #if MPHELL_USE_GMP == 1
2387  return mpz_legendre(src1, src2);
2388 #elif MPHELL_USE_IPP == 1
2389  int len, lenchunk;
2390  ippsRef_BN(NULL, &len, NULL, src2);
2391  lenchunk = bits_to_nblock(len);
2392  number tmp;
2393  number_tmp_alloc(&tmp, lenchunk, stack);
2394  number_copy(tmp, src2);
2395  number_dec(tmp, tmp); /* p-1 */
2396  number_div_ui(tmp, tmp, 2); /* (p-1)/2 */
2397  number_powm(tmp, src1, tmp, src2, stack); /* src1^((p-1)/2) */
2398  if(number_isequal_ui(tmp, 1))
2399  {
2400  number_tmp_free(&tmp, lenchunk, stack);
2401  return 1;
2402  }
2403  else if (number_iszero(tmp))
2404  {
2405  number_tmp_free(&tmp, lenchunk, stack);
2406  return 0;
2407  }
2408  else
2409  {
2410  number_tmp_free(&tmp, lenchunk, stack);
2411  return -1;
2412  }
2413 #elif MPHELL_USE_MBEDTLS == 1
2414  number tmp, tmp1;
2415  uint8_t size = src2->n;
2416  number_tmp_alloc(&tmp, size, stack);
2417  number_tmp_alloc(&tmp1, size+1, stack);
2418  number_copy(tmp, src2);
2419  number_dec(tmp, tmp); /* p-1 */
2420  number_div_ui(tmp, tmp, 2); /* (p-1)/2 */
2421  number_powm(tmp1, src1, tmp, src2, stack); /* src1^((p-1)/2) */
2422  if(number_isequal_ui(tmp1, 1))
2423  {
2424  number_tmp_free(&tmp, size, stack);
2425  number_tmp_free(&tmp1, size+1, stack);
2426  return 1;
2427  }
2428  else if (number_iszero(tmp1))
2429  {
2430  number_tmp_free(&tmp, size, stack);
2431  number_tmp_free(&tmp1, size+1, stack);
2432  return 0;
2433  }
2434  else
2435  {
2436  number_tmp_free(&tmp, size, stack);
2437  number_tmp_free(&tmp1, size+1, stack);
2438  return -1;
2439  }
2440 #endif
2441 }
2442 
2443 void
2444 number_gcd_ui (block * dst, number_srcptr src1, const block src2)
2445 {
2446 #if MPHELL_USE_GMP == 1
2447  *dst = mpz_gcd_ui(NULL, src1, src2);
2448 #elif MPHELL_USE_IPP == 1
2449  number b;
2450  number_init(&b, 1);
2451  number d;
2452  number_init(&d, 1);
2453  number_set_ui(b, src2);
2454  ippsGcd_BN(src1, b, d);
2455  Ipp32u * data;
2456  ippsRef_BN(NULL, NULL, &data, d);
2457  *dst = data[0];
2458  number_free(&b);
2459  number_free(&d);
2460 #elif MPHELL_USE_MBEDTLS == 1
2461  mbedtls_mpi B, C;
2462  mbedtls_mpi_uint p[1];
2463  mbedtls_mpi_uint q[1];
2464  B.s = 1;
2465  B.n = 1;
2466  B.p = p;
2467  C.s = 1;
2468  C.n = 1;
2469  C.p = q;
2470  C.p[0] = src2;
2471  mbedtls_mpi_gcd(&B, src1, &C);
2472  *dst = B.p[0];
2473 #endif
2474 }
2475 
2476 void
2477 number_gcd (number_ptr dst, number_srcptr src1, number_srcptr src2)
2478 {
2479 #if MPHELL_USE_GMP == 1
2480  mpz_gcd(dst, src1, src2);
2481 #elif MPHELL_USE_IPP == 1
2482  ippsGcd_BN(src1, src2, dst);
2483 #elif MPHELL_USE_MBEDTLS == 1
2484  mbedtls_mpi_gcd(dst, src1, src2);
2485 #endif
2486 }
2487 
2488 uint8_t
2489 number_Rabin_Miller (number_srcptr src, const uint16_t bound)
2490 {
2491 #if MPHELL_USE_GMP == 1
2492  return mpz_probab_prime_p(src, (int)bound);
2493 #elif MPHELL_USE_IPP == 1
2494  Ipp32u res;
2495  int ctxSize;
2496  int len;
2497  ippsRef_BN(NULL, &len, NULL, src);
2498 
2499  /* Define Prime context */
2500  ippsPrimeGetSize(len, &ctxSize);
2501  IppsPrimeState* pPrimeG = (IppsPrimeState*)(malloc(ctxSize) );
2502  ippsPrimeInit(len, pPrimeG);
2503 
2504  /* Define Pseudo Random Generator (default settings) */
2505  ippsPRNGGetSize(&ctxSize);
2506  IppsPRNGState* pRand = (IppsPRNGState*)(malloc(ctxSize));
2507  ippsPRNGInit(160, pRand);
2508  ippsPrimeTest_BN(src, (int) bound, &res, pPrimeG, ippsPRNGen, pRand);
2509 
2510  free(pPrimeG);
2511  free(pRand);
2512  if (res == IPP_IS_PRIME)
2513  {
2514  return 1;
2515  }
2516  return 0;
2517 #elif MPHELL_USE_MBEDTLS == 1
2518  number tmp;
2519  number_init(&tmp, src->n);
2520  number_copy(tmp, src);
2521  while(tmp->p[tmp->n-1]==0)
2522  {
2523  tmp->n--;
2524  }
2525  int ret = mbedtls_mpi_is_prime(tmp, mphell_rng, NULL);
2526  number_free(&tmp);
2527  if (ret == 0)
2528  {
2529  return 1;
2530  }
2531  return 0;
2532 #endif
2533 }
2534 
uint8_t number_block_size(number_srcptr src)
Calculate the number of block used by src.
bool number_isdiff_ui(number_srcptr src1, const block src2)
Test if src1 != src2.
bool number_isdiff(number_srcptr src1, number_srcptr src2)
Test if src1 != src2.
bool number_iszero(number_srcptr src)
Test if src is zero.
void number_mod_ui(block *dst, number_srcptr src1, const block src2)
Compute dst such that src1 = q * src2 + dst ; dst < src2.
void number_div_ui(number_ptr dst, number_srcptr src1, const block src2)
Compute dst such that src1 = dst * src2 + r ; r < src2.
void number_invmod(number_ptr dst, number_srcptr src1, number_srcptr src2)
Compute dst such that dst = src1^(-1) mod src2.
uint16_t number_log2(number_srcptr src)
Calculate log2(src), which is the binary size of src.
void mphell_error(char *expr)
Write in stderr, filename, line and expr, free mphell.
Definition: mphell-errors.c:45
void number_powm_ui(number_ptr dst, number_srcptr src1, const block src2, number_srcptr mod, uint8_t stack)
Set dst to src1^src2 modulo mod.
uint8_t number_Rabin_Miller(number_srcptr src, const uint16_t bound)
Apply the Rabin-Miller test to src with the bound.
void number_to_bit_string(char *str, number_srcptr src)
Converts src (must be positive) to a bit string.
void number_get_ui(block *dst, number_srcptr src)
Get the less significant block of src.
void number_mul_ui(number_ptr dst, number_srcptr src1, const block src2)
Set dst to src1 * src2.
void number_set_bit(number_ptr dst, const uint32_t bit)
Set the bit-th of dst to 1, all the others to 0.
void number_set_ui(number_ptr dst, const block src)
Set dst to src.
bool number_iseven(number_srcptr src)
Test if src is even.
void number_div(number_ptr dst, number_srcptr src1, number_srcptr src2)
Compute dst such that src1 = dst * src2 + r ; r < src2.
uint8_t bits_to_nblock(const uint16_t nbits)
Return the number of blocks required to store a nbits number.
Definition: mphell-util.c:29
void number_addmul(number_ptr dst, number_srcptr src1, number_srcptr src2)
Set dst to dst + src1 * src2.
void redcify(number_ptr dst, number_srcptr src, number_srcptr p, uint8_t stack)
Set dst to redc form dst=B^n*src mod p.
bool number_isgreater(number_srcptr src1, number_srcptr src2)
Test if src1 > src2.
void number_mul_montgomery(number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr p, const block invp, uint8_t stack)
Compute dst such that dst = (src1 * src2) mod(p) into the Montgomery form.
void number_gcd(number_ptr dst, number_srcptr src1, number_srcptr src2)
Set dst to GCD(src1, src2)
void number_random1(number_ptr dst, number_srcptr bound, uint8_t stack)
Set dst to a random number_ptr between 0 and bound, the random process is chosen at the MPHELL initia...
void number_free(number *dst)
Free a number_ptr allocated on the RAM memory (malloc)
Definition: mphell-number.c:75
void number_divmod_ui(number_ptr q, block *r, number_srcptr src1, const block src2)
Compute (q, r) such that src1 = q * src2 + r ; r < src2.
bool number_isgreatereq_ui(number_srcptr src1, const block src2)
Test if src1 >= src2.
bool number_isequal_ui(number_srcptr src1, const block src2)
Test if src1 == src2.
int mphell_rng(void *param, unsigned char *res, size_t n)
Set res to n random bytes.
Definition: mphell-init.c:84
void number_lshift(number_ptr dst, number_srcptr src, const uint16_t shift)
Set dst to src << shift.
void number_xor_ui(number_ptr dst, number_srcptr src1, const block src2, uint8_t stack)
Apply logical bitwise XOR operator between src1 and src2.
void number_mul(number_ptr dst, number_srcptr src1, number_srcptr src2)
Set dst to src1 * src2.
bool number_islowereq_ui(number_srcptr src1, const block src2)
Test if src1 <= src2.
void number_gcd_ui(block *dst, number_srcptr src1, const block src2)
Set dst to GCD(src1, src2)
bool number_islowereq(number_srcptr src1, number_srcptr src2)
Test if src1 <= src2.
bool number_isgreater_ui(number_srcptr src1, const block src2)
Test if src1 > src2.
uint8_t number_buffer_size(number_srcptr src)
Give the number of block that src can use.
block number_and_ui(number_srcptr src1, const block src2, uint8_t stack)
Apply logical bitwise AND operator between src1 and src2.
void number_set(number_ptr dst, const int8_t sign, const uint32_t size,...)
Set dst to [block_0, block_1, ..., block_(size-1)]. SIZ(dst) must be set before use.
void number_copy(number_ptr dst, number_srcptr src)
Copy src into dst.
Definition: mphell-number.c:87
void number_sqr(number_ptr dst, number_srcptr src)
Set dst to src1^2.
void number_sub(number_ptr dst, number_srcptr src1, number_srcptr src2)
Set dst to src1 - src2 if src1 - src2 fit in dst.
Declaration of arithmetic functions, interface to chose either GMP mpz or number as base type for ari...
void number_or(number_ptr dst, number_srcptr src1, number_srcptr src2)
Apply logical bitwise OR operator between src1 and src2.
bool number_islower(number_srcptr src1, number_srcptr src2)
Test if src1 < src2.
void number_random(number_ptr dst, const uint32_t size)
Set dst to a random number, the random process is chosen at the MPHELL initialisation....
void number_sub_ui(number_ptr dst, number_srcptr src1, const block src2)
Set dst to src1 - src2 if src1 - src2 fit in dst.
void number_mul_mod(number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr mod, uint8_t stack)
Set dst to (src1 * src2) % mod.
void number_tmp_free(number *t, const uint8_t size, uint8_t stack)
Free a temporary number.
Definition: mphell-number.c:45
void number_powm(number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr mod, uint8_t stack)
Set dst to src1^src2 modulo mod.
void number_inv_montgomery(number_ptr dst, number_srcptr src, number_srcptr p, const block invp, number_srcptr R2, number_srcptr one, uint8_t stack)
Compute dst such that dst = src^(-1) mod(p) into the Montgomery form.
void number_xor(number_ptr dst, number_srcptr src1, number_srcptr src2)
Apply logical bitwise XOR operator between src1 and src2.
void number_dec(number_ptr dst, number_srcptr src)
Set dst to src - 1 if src - 1 fit in dst.
void number_inc(number_ptr dst, number_srcptr src)
Set dst to src + 1 if src + 1 fit in dst.
void number_add(number_ptr dst, number_srcptr src1, number_srcptr src2)
Set dst to src1 + src2 if src1 + src2 fit in dst.
void number_set_str(number_ptr dst, const char *str, const uint8_t base)
Set dst to str.
void number_tmp_alloc(number *t, const uint8_t size, uint8_t stack)
Allocate a temporary number.
Definition: mphell-number.c:31
int8_t number_legendre(number_srcptr src1, number_srcptr src2, uint8_t stack)
Compute the legendre symbole of src1 and src2.
void number_init(number *dst, const uint8_t n)
Allocate a number_ptr on the RAM memory (malloc)
Definition: mphell-number.c:59
bool number_isodd(number_srcptr src)
Test if src is odd.
int8_t number_cmp(number_srcptr src1, number_srcptr src2)
Compare src1 and src2.
bool number_isgreatereq(number_srcptr src1, number_srcptr src2)
Test if src1 >= src2.
void number_print(number_srcptr src, const uint8_t base)
Print src in base "base".
void number_mod(number_ptr dst, number_srcptr src1, number_srcptr src2)
Compute dst such that src1 = q * src2 + dst ; dst < src2.
bool number_islower_ui(number_srcptr src1, const block src2)
Test if src1 < src2.
void number_rshift(number_ptr dst, number_srcptr src, const uint16_t shift)
Set dst to src >> shift.
void number_mul_montgomery_block(number_ptr dst, number_srcptr src1, number_srcptr src2, number_srcptr p, const block invp, uint8_t stack)
Compute dst such that dst = (src1 * src2) mod(p) into the Montgomery form, use when SIZ(src1) or SIZ(...
void number_or_ui(number_ptr dst, number_srcptr src1, const block src2, uint8_t stack)
Apply logical bitwise OR operator between src1 and src2.
void number_and(number_ptr dst, number_srcptr src1, number_srcptr src2)
Apply logical bitwise AND operator between src1 and src2.
void number_inv_mod_basis(block *dst, const block src)
Compute dst such that dst * (-src) = -1 mod (2^(BLOCK_SIZE))
void number_pow(number_ptr dst, number_srcptr src1, number_srcptr src2, uint8_t stack)
Set dst to src1^src2.
int8_t number_cmp_ui(number_srcptr src1, const block src2)
Compare src1 and src2.
void number_divmod(number_ptr q, number_ptr r, number_srcptr src1, number_srcptr src2)
Compute (q, r) such that src1 = q * src2 + r ; r < src2.
bool number_isequal(number_srcptr src1, number_srcptr src2)
Test if src1 == src2.
void number_str(char **str, number_srcptr src, const uint8_t base)
Converts src to string format in base specified by base.
void number_add_ui(number_ptr dst, number_srcptr src1, const block src2)
Set dst to src1 + src2 if src1 + src2 fit in dst.
void number_addmul_ui(number_ptr dst, number_srcptr src1, const block src2)
Set dst to dst + src1 * src2.