MPHELL  4.0.0
mphell-fp.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-fp.h"
27 
28 /*************************************DEBUG***********************************/
29 
39 void
40 fp_elt_print (fp_elt_srcptr src, const uint8_t base, const bool lift, const fp_param param, uint8_t stack)
41 {
42  char *str;
43  fp_elt_str(&str, src, base, lift, param, stack);
44  printf("%s", str);
45  free(str);
46 }
47 
48 
49 /**************************************TMP************************************/
50 
51 /* void fp_elt_get_pool_elt (fp_elt * dst, const fp_param param, uint8_t stack){} is inline */
52 
53 /* void fp_elt_relax_pool_elt (fp_elt * dst, const fp_param param, uint8_t stack){} is inline */
54 
55 /************************************SETTERS**********************************/
56 
57 void
58 fp_alloc (fp_param param, const uint8_t size)
59 {
60  uint8_t i;
61  param->size = size;
62  MPHELL_ASSERT(size >= 1, "fp_alloc : size specified is 0");
63  number_init(&(param->p), size);
64  for (i=0; i<7; i++)
65  {
66  number_init(&(param->pm[i]), size);
67  }
68  fp_elt_alloc(&(param->one), param);
69 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
70 #if MPHELL_USE_MONTGOMERY == 1
71  number_init(&(param->R2), size);
72 #endif
73  number_init(&(param->p_odd), size);
74  fp_elt_alloc(&(param->non_residue), param);
75  fp_elt_alloc(&(param->gen_2sylow), param);
76 #elif MPHELL_USE_IPP == 1
77  int ctxsize;
78  /* ippsGFpGetSize takes size in bits */
79  ippsGFpGetSize(size*32, &ctxsize);
80  param->gf = (IppsGFpState *)malloc(ctxsize * sizeof(Ipp8u));
81 #endif
82  /* Pools creation */
83  param->i_1 = 0;
84  for(i=0; i<POOL_SIZE_FP; i++)
85  {
86  fp_elt_alloc(&(param->pool_1)[i], param);
87  }
88 #if MPHELL_USE_MULTITHREADING == 1
89  param->i_2 = 0;
90  for(i=0; i<POOL_SIZE_FP; i++)
91  {
92  fp_elt_alloc(&(param->pool_2)[i], param);
93  }
94 #endif
95 }
96 
103 void
104 fp_prepare_sqrt(fp_param param, uint8_t stack)
105 {
106 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
107  do
108  {
109  fp_elt_random(param->non_residue, param, stack);
110  } while (fp_elt_issquare(param->non_residue, param, stack));
111  number_dec(param->p_odd, param->p);
112  param->p_even = 0;
113  while (number_iseven(param->p_odd))
114  {
115  ++(param->p_even);
116  number_rshift(param->p_odd, param->p_odd, 1);
117  }
118  fp_elt_pow_number(param->gen_2sylow, param->non_residue, param->p_odd, param, stack);
119 #endif
120 }
121 
122 /*
123  * Initialize the different fps of the structure pointed by k.
124  */
125 void
126 fp_create (fp_param param, number_srcptr p, fp_id id, uint8_t stack)
127 {
128  uint8_t i;
129  number_copy(param->p, p);
130  for (i=0; i<7; i++)
131  {
132  number_mul_ui(param->pm[i], param->p, i+1);
133  }
134 
135  /* For FLT */
136 /* number pm2;*/
137 /* number_tmp_alloc(&pm2, number_block_size(p), stack);*/
138 /* number_sub_ui(pm2, p, 2);*/
139 /* number_str(&(param->pm2), pm2, 2);*/
140 /* number_tmp_free(&pm2, number_block_size(p), stack);*/
141 
142 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
143  MPHELL_ASSERT(param->size >= 1, "fp_create : k is not well allocated");
144  MPHELL_ASSERT((SIZ(p) <= param->size), "fp_create : The size of p is different from the size used to allocate k");
145  //MPHELL_ASSERT_ALWAYS(number_Rabin_Miller(p, 50)>0, "p is not prime \n");
146  fp_elt_init(param->one, param);
147  fp_elt_init(param->non_residue, param);
148  fp_elt_init(param->gen_2sylow, param);
149 #if MPHELL_USE_MONTGOMERY == 1
150  uint8_t n = param->size;
151 
152  /* Compute the Montgomery basis R2 = R^2 mod p */
153  /* Base B = 2^BLOCK_SIZE */
154  /* Base R = (2^BLOCK_SIZE)^n such that R > p */
155 
156  /* param->invp = p' such that (-p)*p' = 1 mod B */
157 
158  number_inv_mod_basis(&(param->invp), LIMB(p)[0]);
159 
160  /* R = 2^(n*BLOCK_SIZE) */
161  number R;
162  number_tmp_alloc(&R, n+1, stack);
163  number_set_ui(R, 1);
164  number_lshift(R, R, n*BLOCK_SIZE);
165 
166  /* R mod p = 2^(n*BLOCK_SIZE) mod p */
167  number Rmodp;
168  number_tmp_alloc(&Rmodp, n, stack);
169  number_mod(Rmodp, R, p);
170 
171  /* R2 = R^2 mod p */
172  number tmp1;
173  number_tmp_alloc(&tmp1, 2 * n, stack);
174  number_sqr(tmp1, Rmodp);
175  number_mod(param->R2, tmp1, p);
176 
177  number_tmp_free(&R, n+1, stack);
178  number_tmp_free(&Rmodp, n, stack);
179  number_tmp_free(&tmp1, 2 * n, stack);
180 
181  /* Compute one into the Montgomery basis */
182  number_tmp_alloc(&tmp1, n, stack);
183  number_set_ui(tmp1, 1);
184  number_mul_montgomery(*(param->one), tmp1, param->R2, p, param->invp, stack);
185  number_tmp_free(&tmp1, n, stack);
186 #else
187  number_set_ui(*(param->one), 1);
188 #endif
189 #elif MPHELL_USE_IPP == 1
190  int len;
191  IppStatus st;
192  switch(id)
193  {
194  case ARBITRARY:
195  ippsRef_BN(NULL, &len, NULL, p);
196  st = ippsGFpInitArbitrary(p, len, param->gf);
197  if(st != ippStsNoErr)
198  {
199  printf("Error fp_create: ippsGFpInitArbitrary: %s\n", ippcpGetStatusString(st));
200  }
201  break;
202  case P192R1:
203  st = ippsGFpInitFixed(192, ippsGFpMethod_p192r1(), param->gf);
204  if(st != ippStsNoErr)
205  {
206  printf("Error fp_create: ippsGFpInitArbitrary: %s\n", ippcpGetStatusString(st));
207  }
208  break;
209  case P224R1:
210  st = ippsGFpInitFixed(224, ippsGFpMethod_p224r1(), param->gf);
211  if(st != ippStsNoErr)
212  {
213  printf("Error fp_create: ippsGFpInitArbitrary: %s\n", ippcpGetStatusString(st));
214  }
215  break;
216  case P256R1:
217  st = ippsGFpInitFixed(256, ippsGFpMethod_p256r1(), param->gf);
218  if(st != ippStsNoErr)
219  {
220  printf("Error fp_create: ippsGFpInitArbitrary: %s\n", ippcpGetStatusString(st));
221  }
222  break;
223  case P384R1:
224  st = ippsGFpInitFixed(384, ippsGFpMethod_p384r1(), param->gf);
225  if(st != ippStsNoErr)
226  {
227  printf("Error fp_create: ippsGFpInitArbitrary: %s\n", ippcpGetStatusString(st));
228  }
229  break;
230  case P521R1:
231  st = ippsGFpInitFixed(521, ippsGFpMethod_p521r1(), param->gf);
232  if(st != ippStsNoErr)
233  {
234  printf("Error fp_create: ippsGFpInitArbitrary: %s\n", ippcpGetStatusString(st));
235  }
236  break;
237  }
238 
239  fp_elt_init(param->one, param);
240  Ipp32u one = 1;
241  st = ippsGFpSetElement(&one, 1, param->one, param->gf);
242  if(st != ippStsNoErr)
243  {
244  printf("Error fp_create: ippsGFpSetElement: %s\n", ippcpGetStatusString(st));
245  }
246 #endif
247  /* Pools creation */
248  param->i_1 = 0;
249  for(i=0; i<POOL_SIZE_FP; i++)
250  {
251  fp_elt_init((param->pool_1)[i], param);
252  }
253 #if MPHELL_USE_MULTITHREADING == 1
254  param->i_2 = 0;
255  for(i=0; i<POOL_SIZE_FP; i++)
256  {
257  fp_elt_init((param->pool_2)[i], param);
258  }
259 #endif
260 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
261  fp_prepare_sqrt(param, stack);
262 #endif
263 }
264 
265 void
266 fp_copy (fp_param param_res, const fp_param param)
267 {
268 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
269  MPHELL_ASSERT(param_res->size == param->size, "fp_copy : The size of k_res \
270  is different from the size of k");
271  number_copy(param_res->p, param->p);
272  int i;
273  for (i=0; i<7; i++)
274  {
275  number_copy(param_res->pm[i], param->pm[i]);
276  }
277  fp_elt_copy(param_res->one, param->one, param);
278 #if MPHELL_USE_MONTGOMERY == 1
279  number_copy(param_res->R2, param->R2);
280  param_res->invp = param->invp;
281 #endif
282  fp_elt_copy(param_res->non_residue, param->non_residue, param);
283  fp_elt_copy(param_res->gen_2sylow, param->gen_2sylow, param);
284  number_copy(param_res->p_odd, param->p_odd);
285  param_res->p_even = param->p_even;
286 #elif MPHELL_USE_IPP == 1
287  /* Todo */
288 #endif
289 }
290 
291 void
293 {
294  /* Pools free */
295  uint8_t i;
296  param->i_1 = 0;
297  for(i=0; i<POOL_SIZE_FP; i++)
298  {
299  fp_elt_free(&(param->pool_1)[i]);
300  }
301  number_free(&param->p);
302  for (i=0; i<7; i++)
303  {
304  number_free(&(param->pm[i]));
305  }
306  fp_elt_free(&param->one);
307 /* free(param->pm2);*/
308 #if MPHELL_USE_MULTITHREADING == 1
309  param->i_2 = 0;
310  for(i=0; i<POOL_SIZE_FP; i++)
311  {
312  fp_elt_free(&(param->pool_2)[i]);
313  }
314 #endif
315 
316 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
317 #if MPHELL_USE_MONTGOMERY == 1
318  number_free(&param->R2);
319  param->invp = (block)0;
320 #endif
321  fp_elt_free(&param->non_residue);
322  fp_elt_free(&param->gen_2sylow);
323  number_free(&param->p_odd);
324  param->p_even = (uint32_t)0;
325  param->size = (uint8_t)0;
326 #elif MPHELL_USE_IPP == 1
327  free(param->gf);
328 #endif
329 }
330 
331 void
332 fp_get_characteristic (number_ptr c, const fp_param param)
333 {
334  number_copy(c, param->p);
335 }
336 
337 /*void*/
338 /*fp_get_pm2 (char * str, const fp_param param)*/
339 /*{*/
340 /* strcpy(str, param->pm2);*/
341 /*}*/
342 
343 void
344 fp_elt_alloc (fp_elt * dst, const fp_param param)
345 {
346 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
347  *dst = (fp_elt)malloc(sizeof(number));
348 #elif MPHELL_USE_IPP == 1
349  /* sizeof(BNU_CHUNK_T): 8 */
350  /* sizeof(IppsGFpElement): 16 */
351  int size = 16 + (param->size)*8;
352  *dst = (fp_elt)malloc(size * sizeof(Ipp8u));
353 #endif
354 }
355 
356 void
357 fp_elt_init (fp_elt_ptr dst, const fp_param param)
358 {
359 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
360  number_init((number *)dst, (param->size)+2);
361 #elif MPHELL_USE_IPP == 1
362  ippsGFpElementInit(NULL, 0, dst, param->gf);
363 #endif
364 }
365 
366 void
367 fp_elt_copy (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param)
368 {
369 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
370  number_copy(*dst, *src);
371 #elif MPHELL_USE_IPP == 1
372  ippsGFpCpyElement(src, dst, param->gf);
373 #endif
374 }
375 
376 void
377 fp_elt_clear (fp_elt * src)
378 {
379 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
380  number_free((number *)*src);
381 #endif
382 }
383 
384 void
385 fp_elt_free (fp_elt * src)
386 {
387 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
388  number_free((number *)*src);
389 #endif
390  free(*src);
391 }
392 
393 void
394 fp_elt_set_one (fp_elt_ptr dst, const fp_param param)
395 {
396 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
397  number_copy(*dst, *param->one);
398 #elif MPHELL_USE_IPP == 1
399  fp_elt_copy(dst, param->one, param);
400 #endif
401 }
402 
403 void
404 fp_elt_set_zero (fp_elt_ptr dst, const fp_param param)
405 {
406 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
407  number_set_ui(*dst, 0);
408 #elif MPHELL_USE_IPP == 1
409  Ipp32u zero = 0;
410  ippsGFpSetElement(&zero, 1, dst, param->gf);
411 #endif
412 }
413 
414 void
415 fp_elt_set_ui (fp_elt_ptr dst, const block src, const bool isreduced,
416  const fp_param param, uint8_t stack)
417 {
418 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
419  number_set_ui(*dst, src);
420 #if MPHELL_USE_MONTGOMERY == 1
421  if(!isreduced)
422  {
423  /* Convert to Montgomery form */
424  redcify(*dst, *dst, param->p, stack);
425  }
426 #endif
427 #elif MPHELL_USE_IPP == 1
428  ippsGFpSetElement(&src, 1, dst, param->gf);
429 #endif
430 }
431 
432 void
433 fp_elt_set_number (fp_elt_ptr dst, number_srcptr src, const bool isreduced,
434  const fp_param param, uint8_t stack)
435 {
436 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
437  number_copy(*dst, src);
438 #if MPHELL_USE_MONTGOMERY == 1
439  if(!isreduced)
440  {
441  /* Convert to Montgomery form */
442  redcify(*dst, *dst, param->p, stack);
443  }
444 #endif
445 #elif MPHELL_USE_IPP == 1
446  int len, lenchunk;
447  Ipp32u * data;
448  ippsRef_BN(NULL, &len, &data, src);
449  lenchunk = bits_to_nblock(len);
450  ippsGFpSetElement(data, lenchunk, dst, param->gf);
451 #endif
452 }
453 
454 void
455 fp_elt_set_str (fp_elt_ptr dst, const char *str, const uint8_t base,
456  const bool isreduced, const fp_param param, uint8_t stack)
457 {
458 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
459  number_set_str(*dst, str, base);
460 #if MPHELL_USE_MONTGOMERY == 1
461  if(!isreduced)
462  {
463  /* Convert to Montgomery form */
464  redcify(*dst, *dst, param->p, stack);
465  }
466 #endif
467 #elif MPHELL_USE_IPP == 1
468  number tmp;
469  number_tmp_alloc(&tmp, param->size, stack);
470  number_set_str(tmp, str, base);
471  int len, lenchunk;
472  Ipp32u * data;
473  ippsRef_BN(NULL, &len, &data, tmp);
474  lenchunk = bits_to_nblock(len);
475  ippsGFpSetElement(data, lenchunk, dst, param->gf);
476  number_tmp_free(&tmp, param->size, stack);
477 #endif
478 }
479 
480 void
481 fp_elt_random (fp_elt_ptr dst, const fp_param param, uint8_t stack)
482 {
483 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
484  number_random1 (*dst, param->p, stack);
485 #if MPHELL_USE_MONTGOMERY == 1
486  /* Convert to Montgomery form */
487  redcify(*dst, *dst, param->p, stack);
488 #endif
489 #elif MPHELL_USE_IPP == 1
490  number tmp;
491  number_tmp_alloc(&tmp, param->size, stack);
492  number_random1(tmp, param->p, stack);
493  int len, lenchunk;
494  Ipp32u * data;
495  ippsRef_BN(NULL, &len, &data, tmp);
496  lenchunk = bits_to_nblock(len);
497  ippsGFpSetElement(data, lenchunk, dst, param->gf);
498  number_tmp_free(&tmp, param->size, stack);
499 #endif
500 }
501 
502 void
503 fp_elt_lift (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
504 {
505 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
506 #if MPHELL_USE_MONTGOMERY == 1
507  number tmp;
508  number_tmp_alloc(&tmp, 1, stack);
509  /* Convert to Normal form (from Montgomery form) */
510  number_set_ui(tmp, 1);
511  number_mul_montgomery_block(*dst, *src, tmp, param->p, param->invp, stack);
512  number_tmp_free(&tmp, 1, stack);
513 #else
514  number_copy(*dst, *src);
515 #endif
516 #elif MPHELL_USE_IPP == 1
517  fp_elt_copy(dst, src, param);
518 #endif
519 }
520 
521 void
522 fp_elt_get_number (number_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
523 {
524 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
525 #if MPHELL_USE_MONTGOMERY == 1
526  number tmp;
527  number_tmp_alloc(&tmp, 1, stack);
528  /* Convert to Normal form (from Montgomery form) */
529  number_set_ui(tmp, 1);
530  number_mul_montgomery_block(dst, *src, tmp, param->p, param->invp, stack);
531  number_tmp_free(&tmp, 1, stack);
532 #else
533  number_copy(dst, *src);
534 #endif
535 #elif MPHELL_USE_IPP == 1
536  Ipp32u data[param->size];
537  ippsGFpGetElement(src, data, param->size, param->gf);
538  ippsSet_BN(IppsBigNumPOS, param->size, data, dst);
539 #endif
540 }
541 
542 void
543 fp_str (char **str, const fp_param param, const uint8_t base, uint8_t stack)
544 {
545 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
546  uint16_t strsize=0;
547  char *p_str, *one_str;
548  char *non_residue_str, *p_odd_str, *gen_2sylow_str;
549 #if MPHELL_USE_MONTGOMERY == 1
550  char *R2_str;
551 #endif
552  number_str(&p_str, param->p, base);
553  fp_elt_str(&one_str, param->one, base, false, param, stack);
554  number_str(&p_odd_str, param->p_odd, base);
555  fp_elt_str(&non_residue_str, param->non_residue, base, true, param, stack);
556  fp_elt_str(&gen_2sylow_str, param->gen_2sylow, base, true, param, stack);
557 #if MPHELL_USE_MONTGOMERY == 1
558  number_str(&R2_str, param->R2, base);
559 #endif
560  strsize = 250 + strlen(p_str) + strlen(one_str);
561  strsize += strlen(non_residue_str) + strlen(p_odd_str) + strlen(gen_2sylow_str);
562 #if MPHELL_USE_MONTGOMERY == 1
563  strsize += strlen(R2_str);
564 #endif
565  *str = (char*)malloc(strsize*sizeof(char));
566  char *s = *str;
567  sprintf(s, "p : %s \none : %s\n", p_str, one_str);
568  sprintf(s + strlen(s), "non_residue : %s\np_odd : %s\
569  \np_even : %d\ngen_2sylow : %s", non_residue_str,
570  p_odd_str, (int)param->p_even, gen_2sylow_str);
571 #if MPHELL_USE_MONTGOMERY == 1
572 #if BLOCK_SIZE == 64
573  sprintf(s + strlen(s), "\nR2 : %s \ninvp : %"PRIu64"\n", R2_str,
574  param->invp);
575 #else
576  sprintf(s + strlen(s), "\nR2 : %s \ninvp : %"PRIu32"\n", R2_str,
577  param->invp);
578 #endif
579 #endif
580  free(p_odd_str);
581  free(non_residue_str);
582  free(gen_2sylow_str);
583 #if MPHELL_USE_MONTGOMERY == 1
584  free(R2_str);
585 #endif
586  free(p_str);
587  free(one_str);
588 #elif MPHELL_USE_IPP == 1
589  uint16_t strsize=0;
590  char *p_str;
591  number_str(&p_str, param->p, base);
592  strsize = 250 + strlen(p_str);
593  *str = (char*)malloc(strsize*sizeof(char));
594  sprintf(*str, "p : %s \n", p_str);
595  free(p_str);
596 #endif
597 }
598 
599 void
600 fp_elt_str (char **str, fp_elt_srcptr src, const uint8_t base,
601  const bool lift, const fp_param param, uint8_t stack)
602 {
603 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
604  if(lift)
605  {
606  fp_elt tmp;
607  fp_elt_get_pool_elt(&tmp, param, stack);
608  fp_elt_lift(tmp, src, param, stack);
609  number_str(str, *tmp, base);
610  fp_elt_relax_pool_elt(&tmp, param, stack);
611  }
612  else
613  {
614  number_str(str, *src, base);
615  }
616 #elif MPHELL_USE_IPP == 1
617  number tmp;
618  number_tmp_alloc(&tmp, param->size, stack);
619  Ipp32u *data = malloc(param->size * sizeof(Ipp32u));
620  ippsGFpGetElement(src, data, param->size, param->gf);
621  ippsSet_BN(IppsBigNumPOS, param->size, data, tmp);
622  number_str(str, tmp, base);
623  number_tmp_free(&tmp, param->size, stack);
624  free(data);
625 #endif
626 }
627 
628 /*************************COMPARISON AND LOGICAL******************************/
629 
630 int8_t
631 fp_elt_cmp (fp_elt_srcptr src1, fp_elt_srcptr src2, const fp_param param)
632 {
633 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
634  return (number_cmp(*src1, *src2));
635 #elif MPHELL_USE_IPP == 1
636  int res;
637  ippsGFpCmpElement(src1, src2, &res, param->gf);
638  if(res == IPP_IS_EQ)
639  {
640  return 0;
641  }
642  else if (res == IPP_IS_GT)
643  {
644  return 1;
645  }
646  else
647  {
648  return -1;
649  }
650 #endif
651 }
652 
653 bool
654 fp_elt_isone (fp_elt_srcptr src, const fp_param param)
655 {
656 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
657  return (number_cmp(*src, *param->one) == 0);
658 #elif MPHELL_USE_IPP == 1
659  int res;
660  ippsGFpIsUnityElement(src, &res, param->gf);
661  return (res == IPP_IS_EQ);
662 #endif
663 }
664 
665 /* bool fp_elt_iszero (fp_elt_srcptr src, const fp_param param){} is inline */
666 
667 /***************************ADDITION SUBTRACTION******************************/
668 
669 /* void fp_elt_inc (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param){} is inline */
670 
671 /* void fp_elt_add (fp_elt_ptr dst, fp_elt_srcptr src1, fp_elt_srcptr src2, const fp_param param){} is inline */
672 
673 /* void fp_elt_dec (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param){} is inline */
674 
675 /* void fp_elt_sub (fp_elt_ptr dst, fp_elt_srcptr src1, fp_elt_srcptr src2, const fp_param param){} is inline */
676 
677 /* void fp_elt_neg (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param){} is inline */
678 
679 /*******************************MULTIPLICATION********************************/
680 
681 /* void fp_elt_mul (fp_elt_ptr dst, fp_elt_srcptr src1, fp_elt_srcptr src2, const fp_param param, uint8_t stack){} is inline */
682 
683 /* void fp_elt_mul2 (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param){} is inline */
684 
685 /* void fp_elt_mul4 (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param){} is inline */
686 
687 /* void fp_elt_mul8 (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param){} is inline */
688 
689 /* void fp_elt_mul3 (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack){} is inline */
690 
691 /* void fp_elt_sqr (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack){} is inline */
692 
693 
694 /*void*/
695 /*fp_elt_inv_flt (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)*/
696 /*{*/
697 /* fp_elt y;*/
698 /* int i;*/
699 /* fp_elt_get_pool_elt(&y, param, stack);*/
700 /* */
701 /* fp_elt_copy(y, src, param);*/
702 /* fp_elt_set_one(dst, param);*/
703 
704 /* for(i=strlen(param->pm2)-1; i>=0; i--)*/
705 /* { */
706 /* if (param->pm2[i]=='1')*/
707 /* {*/
708 /* fp_elt_mul(dst, dst, y, param, stack);*/
709 /* }*/
710 /* fp_elt_sqr(y, y, param, stack);*/
711 /* }*/
712 /* fp_elt_relax_pool_elt(&y, param, stack);*/
713 /*}*/
714 
715 void
716 fp_elt_inv (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
717 {
718  MPHELL_ASSERT(fp_elt_iszero(src, param) == false, "fp_elt_inv : src == 0");
719  if(fp_elt_isone(src, param))
720  {
721  fp_elt_copy(dst, src, param);
722  return;
723  }
724 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
725 #if MPHELL_USE_MONTGOMERY == 1
726  number_inv_montgomery(*dst, *src, param->p, param->invp, param->R2, *param->one, stack);
727 #else
728  number_invmod(*dst, *src, param->p);
729 #endif
730 #elif MPHELL_USE_IPP == 1
731  IppStatus st = ippsGFpInv(src, dst, param->gf);
732  if(st != ippStsNoErr)
733  {
734  printf("Error fp_elt_inv: %s\n", ippcpGetStatusString(st));
735  }
736 #endif
737 }
738 
739 void
740 fp_elt_div (fp_elt_ptr dst, fp_elt_srcptr src1, fp_elt_srcptr src2,
741  const fp_param param, uint8_t stack)
742 {
743  MPHELL_ASSERT(fp_elt_iszero(src2, param) == false, "fp_elt_div : src2 == 0");
744  if(fp_elt_isone(src2, param))
745  {
746  fp_elt_copy(dst, src1, param);
747  return;
748  }
749  if(fp_elt_cmp(src1, src2, param)==0)
750  {
751  fp_elt_set_one(dst, param);
752  return;
753  }
754 
755  fp_elt tmp;
756  fp_elt_get_pool_elt(&tmp, param, stack);
757  fp_elt_inv(tmp, src2, param, stack);
758  fp_elt_mul(dst, src1, tmp, param, stack);
759  fp_elt_relax_pool_elt(&tmp, param, stack);
760 }
761 
762 void
763 fp_elt_pow_ui (fp_elt_ptr dst, fp_elt_srcptr src, const block n,
764  const fp_param param, uint8_t stack)
765 {
766 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
767 #if MPHELL_USE_MONTGOMERY == 1
768  fp_elt y;
769  fp_elt_get_pool_elt(&y, param, stack);
770  block m = n;
771 
772  fp_elt_copy(y, src, param);
773  fp_elt_set_one(dst, param);
774 
775  while (m != (block)0)
776  {
777  if (m & (block)1)
778  {
779  fp_elt_mul(dst, dst, y, param, stack);
780  }
781  fp_elt_sqr(y, y, param, stack);
782  m >>= 1;
783  }
784  fp_elt_relax_pool_elt(&y, param, stack);
785 #else
786  number_powm_ui(*dst, *src, n, param->p, stack);
787 #endif
788 #elif MPHELL_USE_IPP == 1
789  number tmp;
790  number_tmp_alloc(&tmp, param->size, stack);
791  number_set_ui(tmp, n);
792  int sizebuf;
793  ippsGFpScratchBufferSize(1, 32, param->gf, &sizebuf);
794  Ipp8u * buf = malloc(sizebuf * sizeof(Ipp8u));
795  IppStatus st = ippsGFpExp(src, tmp, dst, param->gf, buf);
796  if(st != ippStsNoErr)
797  {
798  printf("Error fp_elt_pow_ui: %s\n", ippcpGetStatusString(st));
799  }
800  free(buf);
801  number_tmp_free(&tmp, param->size, stack);
802 #endif
803 }
804 
805 void
806 fp_elt_pow_number (fp_elt_ptr dst, fp_elt_srcptr src, number_srcptr n,
807  const fp_param param, uint8_t stack)
808 {
809 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
810 #if MPHELL_USE_MONTGOMERY == 1
811  number m;
812  fp_elt y;
813  fp_elt_get_pool_elt(&y, param, stack);
814  number_tmp_alloc(&m, SIZ(n), stack);
815 
816  number_copy(m, n);
817  fp_elt_copy(y, src, param);
818  fp_elt_set_one(dst, param);
819 
820  while (number_isdiff_ui(m, 0))
821  {
822  if (number_and_ui(m, (block)1, stack))
823  {
824  fp_elt_mul(dst, dst, y, param, stack);
825  }
826  fp_elt_sqr(y, y, param, stack);
827  number_rshift(m, m, 1);
828  }
829  fp_elt_relax_pool_elt(&y, param, stack);
830  number_tmp_free(&m, SIZ(n), stack);
831 #else
832  number_powm(*dst, *src, n, param->p, stack);
833 #endif
834 #elif MPHELL_USE_IPP == 1
835  int sizebuf;
836  ippsGFpScratchBufferSize(1, (param->size)*32, param->gf, &sizebuf);
837  Ipp8u * buf = malloc(sizebuf * sizeof(Ipp8u));
838  IppStatus st = ippsGFpExp(src, n, dst, param->gf, buf);
839  if(st != ippStsNoErr)
840  {
841  printf("Error fp_elt_pow_number: %s\n", ippcpGetStatusString(st));
842  }
843  free(buf);
844 #endif
845 }
846 
847 bool
848 fp_elt_issquare (fp_elt_srcptr src, const fp_param param, uint8_t stack)
849 {
850 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
851  return (number_legendre(*src, param->p, stack) == 1);
852 #elif MPHELL_USE_IPP == 1
853  number tmp;
854  number_init(&tmp, param->size);
855  Ipp32u data[param->size];
856  ippsGFpGetElement(src, data, param->size, param->gf);
857  ippsSet_BN(IppsBigNumPOS, param->size, data, tmp);
858  int res = number_legendre(tmp, param->p, stack);
859  number_free(&tmp);
860  return (res == 1);
861 #endif
862 }
863 
864 int8_t
865 fp_elt_ispower_ui (fp_elt_srcptr src, const block n, const fp_param param, uint8_t stack)
866 {
867  if(n == 0)
868  {
869  return (fp_elt_isone(src, param));
870  }
871 
872  if(n == 1)
873  {
874  return true;
875  }
876 
877  if(n == 2)
878  {
879  return (fp_elt_issquare(src, param, stack));
880  }
881 
882  fp_elt y;
883  number m;
884  block r;
885  fp_elt_get_pool_elt(&y, param, stack);
886  number_tmp_alloc(&m, param->size, stack);
887 
888  number_dec(m, param->p); /* m = p - 1 */
889  number_gcd_ui(&r, m, n); /* r <- gcd(m, n) */
890 
891  if (r==1)
892  {
893  /* gcd(p-1, n) = 1 => there exist v ; n.v = 1 mod (p - 1) => by small fermat th, for all a in Z/pZ (a^v)^n = a mod p */
894  fp_elt_relax_pool_elt(&y, param, stack);
895  number_tmp_free(&m, param->size, stack);
896  return 2;
897  }
898 
899  number_div_ui(m, m, r); /* m = p-1 / r */
900 
901  fp_elt_pow_number(y, src, m, param, stack);
902  bool res = fp_elt_isone(y, param); /* Euler criterion: src is a n-power if src^((p-1) / gcd(p-1,n)) == 1 */
903  fp_elt_relax_pool_elt(&y, param, stack);
904  number_tmp_free(&m, param->size, stack);
905  return res;
906 }
907 
908 int8_t
909 fp_elt_ispower_number (fp_elt_srcptr src, number_srcptr n, const fp_param param, uint8_t stack)
910 {
911  if(number_iszero(n))
912  {
913  return (fp_elt_isone(src, param));
914  }
915 
916  if(number_cmp_ui(n , 1) == 0)
917  {
918  return true;
919  }
920 
921  if(number_cmp_ui(n , 2) == 0)
922  {
923  return (fp_elt_issquare(src, param, stack));
924  }
925 
926  fp_elt y;
927  number m, r;
928 
929  fp_elt_get_pool_elt(&y, param, stack);
930  number_tmp_alloc(&m, param->size, stack);
931  number_tmp_alloc(&r, param->size, stack);
932 
933  number_dec(m, param->p); /* m = p - 1 */
934  number_gcd(r, m, n); /* r <- gcd(m, n) */
935 
936  if (number_isequal_ui(r, (block)1))
937  {
938  /* gcd(p-1, n) = 1 => there exist v ; n.v = 1 mod (p - 1) => by small fermat th, for all a in Z/pZ (a^v)^n = a mod p */
939  fp_elt_relax_pool_elt(&y, param, stack);
940  number_tmp_free(&m, param->size, stack);
941  number_tmp_free(&r, param->size, stack);
942  return 2;
943  }
944 
945  number_div(m, m, r); /* m = p-1 / r */
946 
947  fp_elt_pow_number(y, src, m, param, stack);
948  bool res = fp_elt_isone(y, param); /* Euler criterion: src is a n-power if src^((p-1) / gcd(p-1,n)) == 1 */
949  fp_elt_relax_pool_elt(&y, param, stack);
950  number_tmp_free(&m, param->size, stack);
951  number_tmp_free(&r, param->size, stack);
952  return res;
953 }
954 
955 void
956 fp_elt_sqrt (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
957 {
958 #if (MPHELL_USE_GMP == 1 || MPHELL_USE_MBEDTLS == 1)
959  fp_elt r, b, x ;
960  if(fp_elt_iszero(src, param))
961  {
962  fp_elt_set_ui(dst, 0, true, param, stack);
963  return;
964  }
965 
966  fp_elt_get_pool_elt(&r, param, stack);
967  fp_elt_get_pool_elt(&b, param, stack);
968  fp_elt_get_pool_elt(&x, param, stack);
969 
970  number q;
971  number_tmp_alloc(&q, SIZ(param->p_odd)+1, stack);
972  number_inc(q, param->p_odd);
973  number_rshift(q, q, 1);
974  fp_elt_pow_number(x, src, q, param, stack);
975 
976  while (1)
977  {
978  fp_elt_sqr(r, x, param, stack);
979  fp_elt_div(b, r, src, param, stack);
980 
981  if (fp_elt_isone(b, param))
982  {
983  fp_elt_neg(dst, x, param);
984  fp_elt_relax_pool_elt(&r, param, stack);
985  fp_elt_relax_pool_elt(&b, param, stack);
986  number_tmp_free(&q, SIZ(param->p_odd)+1, stack);
987  fp_elt_relax_pool_elt(&x, param, stack);
988  return;
989  }
990 
991  uint32_t m = 0;
992  do
993  {
994  fp_elt_sqr(b, b, param, stack);
995  ++m;
996  MPHELL_ASSERT_ALWAYS(m <= param->p_even, "fp_elt_sqrt : \
997  m > p_even");
998  } while (!fp_elt_isone(b, param));
999 
1000  fp_elt_copy(r, param->gen_2sylow, param);
1001  while (m < param->p_even - 1)
1002  {
1003  fp_elt_sqr(r, r, param, stack);
1004  ++m;
1005  }
1006  fp_elt_mul(x, x, r, param, stack);
1007  }
1008 
1009  fp_elt_relax_pool_elt(&r, param, stack);
1010  fp_elt_relax_pool_elt(&b, param, stack);
1011  number_tmp_free(&q, SIZ(param->p_odd)+1, stack);
1012  fp_elt_relax_pool_elt(&x, param, stack);
1013 #elif MPHELL_USE_IPP == 1
1014  ippsGFpSqrt(src, dst, param->gf);
1015 #endif
1016 }
1017 
1018 void
1019 fp_elt_cube_root (fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
1020 {
1021  number m;
1022  number_tmp_alloc(&m, param->size+1, stack);
1023  block r = (block)0;
1024  number_dec(m, param->p);
1025 
1026  /* Case 1 : p-1 = 1 mod 3 */
1027  number_mod_ui(&r, m, 3);
1028 
1029  if (r == 1)
1030  {
1031  /* gcd(p-1, 3) = 1 => there is v such that 3.v = 1 mod (p-1) => src^v = src^(1/3) mod p */
1032  /* v = (2p - 1) / 3 suit and p-1 = 1 mod 3 => 2p - 1 = 0 mod 3 */
1033 
1034  number_add(m, m, param->p); /* m <- 2*p - 1 */
1035 
1036  number_div_ui(m, m, (block)3); /* m <- (2*p - 1)/3 */
1037  fp_elt_pow_number(dst, src, m, param, stack);
1038  number_tmp_free(&m, param->size+1, stack);
1039  return;
1040  }
1041 
1042  /* Case 2 : p-1 = 3 mod 9 */
1043  number_mod_ui(&r, m, 9);
1044 
1045  if (r == 3)
1046  {
1047  number_add(m, param->p, param->p); /* m <- 2*p */
1048  number_inc(m, m); /* m <- 2*p + 1 */
1049  number_div_ui(m, m, (block)9); /* m <- (2*p + 1)/9 */
1050  fp_elt_pow_number(dst, src, m, param, stack);
1051  number_tmp_free(&m, param->size+1, stack);
1052  return;
1053  }
1054 
1055  /* Case 3 : p-1 = 6 mod 9 */
1056  number_mod_ui(&r, m, 9);
1057 
1058  if (r == 6)
1059  {
1060  number_inc(m, param->p);
1061  number_inc(m, m); /* m <- p + 2 */
1062  number_div_ui(m, m, (block)9); /* m <- (p + 2)/9 */
1063  fp_elt_pow_number(dst, src, m, param, stack);
1064  number_tmp_free(&m, param->size+1, stack);
1065  return;
1066  }
1067 
1068  else
1069  {
1070  /* Case p != 2 mod 3, or p != 4 mod 9 or p != 7 mod 9 */
1071  number t;
1072  number l;
1073  uint32_t s = 0;
1074  uint32_t s1 = 0;
1075  uint32_t i;
1076  uint8_t k;
1077  block pow = (block)1;
1078  block r0;
1079  int8_t r1;
1080  block gcd;
1081  fp_elt b, c1, c2, h, r, d, tmp1;
1082  number_tmp_alloc(&t, param->size, stack);
1083  number_tmp_alloc(&l, param->size, stack);
1084  fp_elt_get_pool_elt(&b, param, stack);
1085  fp_elt_get_pool_elt(&c1, param, stack);
1086  fp_elt_get_pool_elt(&c2, param, stack);
1087  fp_elt_get_pool_elt(&h, param, stack);
1088  fp_elt_get_pool_elt(&r, param, stack);
1089  fp_elt_get_pool_elt(&d, param, stack);
1090  fp_elt_get_pool_elt(&tmp1, param, stack);
1091 
1092  number_dec(t, param->p); /* t <- p-1 */
1093  number_gcd_ui(&gcd, t, (block)3);
1094 
1095  /* Step 1: We write q-1 as t.3^s, with t = 3l +- 1 */
1096  number_mod_ui(&r0, t, (block)3);
1097  while(r0==0)
1098  {
1099  s++;
1100  number_divmod_ui(t, &r0, t, (block)3);
1101  number_mod_ui(&r0, t, (block)3);
1102  }
1103  number_divmod_ui(l, &r0, t, (block)3);
1104 
1105  if(r0 == 2)
1106  {
1107  number_inc(l, l);
1108  r1=-1;
1109  }
1110  else
1111  {
1112  r1 = 1;
1113  }
1114 
1115  /* Step 2: Find a non cubic residue */
1116  do
1117  {
1118  fp_elt_random(b, param, stack);
1119  }
1120  while(fp_elt_ispower_ui(b, (block)3, param, stack)!=0);
1121 
1122  /* Compute c1 and c2 */
1123  fp_elt_pow_number(c1, b, t, param, stack); /* c1 <- b^t */
1124  s1 = s - 1;
1125  while(s1 != 0)
1126  {
1127  pow*=3;
1128  s1--;
1129  }
1130  fp_elt_pow_ui(c2, c1, pow, param, stack); /* c2 <- c1^(3^(s-1)) */
1131 
1132  /* Step 3: Computation of the cube root of (a^t)^(-1) */
1133  fp_elt_set_one(h, param); /* h <- 1 */
1134  fp_elt_pow_number(r, src, t, param, stack); /* r = a^t = src^t */
1135 
1136  for(i=1; i<= (s-1); i++)
1137  {
1138  /* d <- r^(3^(s-i-1)) */
1139  s1 = s-i-1;
1140  pow = (block)1;
1141  while(s1 != 0)
1142  {
1143  pow*=3;
1144  s1--;
1145  }
1146  fp_elt_pow_ui(d, r, pow, param, stack);
1147  if(fp_elt_isone(d, param))
1148  {
1149  k = 0;
1150  }
1151  else if(fp_elt_cmp(d, c2, param)==0)
1152  {
1153  k = 2;
1154  }
1155  else
1156  {
1157  k = 1;
1158  }
1159  fp_elt_pow_ui(tmp1, c1, (block)k, param, stack); /* tmp1 <- c1^k */
1160  fp_elt_mul(h, h, tmp1, param, stack); /* h <- h.c1^k */
1161  fp_elt_pow_ui(tmp1, c1, (block)(k*3), param, stack); /* tmp1 <- c1^3k */
1162  fp_elt_mul(r, r, tmp1, param, stack); /* r <- r.(c1^3)^k */
1163  fp_elt_pow_ui(c1, c1, (block)3, param, stack); /* c1 <- c1^3 */
1164  }
1165 
1166  /* Step 4: */
1167  fp_elt_pow_number(tmp1, src, l, param, stack); /* tmp1 <- a^l */
1168  fp_elt_mul(r, tmp1, h, param, stack); /* r <- (a^l).h */
1169  if(r1 == 1)
1170  {
1171  fp_elt_inv(dst, r, param, stack);
1172  }
1173  else
1174  {
1175  fp_elt_copy(dst, r, param);
1176  }
1177 
1178  number_tmp_free(&t, param->size, stack);
1179  number_tmp_free(&l, param->size, stack);
1180  fp_elt_relax_pool_elt(&b, param, stack);
1181  fp_elt_relax_pool_elt(&c1, param, stack);
1182  fp_elt_relax_pool_elt(&c2, param, stack);
1183  fp_elt_relax_pool_elt(&h, param, stack);
1184  fp_elt_relax_pool_elt(&r, param, stack);
1185  fp_elt_relax_pool_elt(&d, param, stack);
1186  fp_elt_relax_pool_elt(&tmp1, param, stack);
1187  }
1188  number_tmp_free(&m, param->size+1, stack);
1189 }
1190 
1198 void
1199 fp_elt_primitive_elt (fp_elt_ptr dst, const fp_param param, uint8_t stack)
1200 {
1201  /* Find a possible primitive element */
1202  fp_elt a;
1203  fp_elt res;
1204  fp_elt_get_pool_elt(&a, param, stack);
1205  fp_elt_get_pool_elt(&res, param, stack);
1206  number m;
1207  number q;
1208  number_tmp_alloc(&m, param->size, stack);
1209  number_tmp_alloc(&q, param->size, stack);
1210  bool test = true;
1211  block r;
1212  int8_t i = 0;
1213 
1214  number_dec(m, param->p); /* m <- p-1 */
1215 
1216  /* First 20 prime */
1217  block prime[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71};
1218 
1219  do
1220  {
1221  /* Select a random element */
1222  fp_elt_random(a, param, stack);
1223 
1224  /* Suppose that the element is primitive */
1225  test = true;
1226  i = 0;
1227  while(i<20)
1228  {
1229  number_mod_ui(&r, m, prime[i]);
1230  number_divmod_ui(q, &r, m, prime[i]);
1231  if(r == 0)
1232  {
1233  /* prime[i] divides p-1 */
1234  /* q = (p-1) / prime[i] */
1235  fp_elt_pow_number(res, a, q, param, stack);
1236  if(fp_elt_isone(res, param))
1237  {
1238  /* The element is not primitive */
1239  test = false;
1240  break;
1241  }
1242  }
1243  i++;
1244  }
1245  }
1246  while(test == false);
1247 
1248  fp_elt_copy(dst, a, param);
1249 
1250  fp_elt_relax_pool_elt(&a, param, stack);
1251  fp_elt_relax_pool_elt(&res, param, stack);
1252  number_tmp_free(&m, param->size, stack);
1253  number_tmp_free(&q, param->size, stack);
1254 }
1255 
1256 void
1257 fp_elt_unity_nth_root (fp_elt_ptr dst, const block n, const fp_param param, uint8_t stack)
1258 {
1259  /* Find a possible primitive element */
1260  fp_elt a;
1261  fp_elt b;
1262  fp_elt_get_pool_elt(&a, param, stack);
1263  fp_elt_get_pool_elt(&b, param, stack);
1264  number m;
1265  number q;
1266  block r;
1267  number_tmp_alloc(&m, param->size, stack);
1268  number_tmp_alloc(&q, param->size, stack);
1269  number_set_ui(m, (block)0);
1270  number_set_ui(q, (block)0);
1271  number_dec(m, param->p); /* m <- p-1 */
1272  number_divmod_ui(q, &r, m, n); /* q <- (p-1)/n */
1273  if(r != 0)
1274  {
1275  /* There is no non-trivial nth root of unity */
1276  fp_elt_set_one(dst, param);
1277  }
1278  else
1279  {
1280  /* There is a non-trivial nth root of unity */
1281  do
1282  {
1283  /* Set a to a strongly possible primitive element */
1284  fp_elt_primitive_elt (a, param, stack);
1285  /* Set b = a^((p-1)/n) */
1286  fp_elt_pow_number(b, a, q, param, stack);
1287  }
1288  while(fp_elt_isone(b, param));
1289 
1290  fp_elt_copy(dst, b, param);
1291  }
1292 
1293  fp_elt_relax_pool_elt(&a, param, stack);
1294  fp_elt_relax_pool_elt(&b, param, stack);
1295  number_tmp_free(&m, param->size, stack);
1296  number_tmp_free(&q, param->size, stack);
1297 }
1298 
bool number_isdiff_ui(number_srcptr src1, const block src2)
Test if src1 != src2.
bool number_iszero(number_srcptr src)
Test if src is zero.
int8_t fp_elt_cmp(fp_elt_srcptr src1, fp_elt_srcptr src2, const fp_param param)
Compare src1 and src2 in Fp.
Definition: mphell-fp.c:631
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 fp_elt_pow_number(fp_elt_ptr dst, fp_elt_srcptr src, number_srcptr n, const fp_param param, uint8_t stack)
Set dst <- src^n.
Definition: mphell-fp.c:806
void number_invmod(number_ptr dst, number_srcptr src1, number_srcptr src2)
Compute dst such that dst = src1^(-1) mod src2.
void fp_elt_set_ui(fp_elt_ptr dst, const block src, const bool isreduced, const fp_param param, uint8_t stack)
Set dst to src, if Montgomery arithmetic is used, is_reduced == false -> transform dst into its Montg...
Definition: mphell-fp.c:415
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.
void fp_elt_free(fp_elt *src)
Free space used by src.
Definition: mphell-fp.c:385
void number_mul_ui(number_ptr dst, number_srcptr src1, const block src2)
Set dst to src1 * src2.
void fp_elt_clear(fp_elt *src)
Clear space used by src (remove the action of fp_elt_init but let the one of fp_elt_alloc)
Definition: mphell-fp.c:377
void number_set_ui(number_ptr dst, const block src)
Set dst to src.
enum fp_id_e fp_id
Identifier for known field, use by IPPCP to accelerate the field arithmetic.
Definition: mphell-fp.h:143
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 fp_elt_pow_ui(fp_elt_ptr dst, fp_elt_srcptr src, const block n, const fp_param param, uint8_t stack)
Set dst <- src^n.
Definition: mphell-fp.c:763
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.
static void fp_elt_sqr(fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
Set dst <- src^2.
Definition: mphell-fp.h:806
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.
static void fp_elt_relax_pool_elt(fp_elt *dst, const fp_param param, uint8_t stack)
Relax an initialised field element from the pool.
Definition: mphell-fp.h:195
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.
void fp_create(fp_param param, number_srcptr p, fp_id id, uint8_t stack)
Create a prime field of characteristic p.
Definition: mphell-fp.c:126
bool number_isequal_ui(number_srcptr src1, const block src2)
Test if src1 == src2.
void fp_elt_copy(fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param)
Copy src into dst, src and dst must belong to the same Fp.
Definition: mphell-fp.c:367
void fp_get_characteristic(number_ptr c, const fp_param param)
Get the characteristic of the prime field "param".
Definition: mphell-fp.c:332
void fp_free(fp_param param)
Free the space of the prime field informations structure.
Definition: mphell-fp.c:292
void fp_prepare_sqrt(fp_param param, uint8_t stack)
Find a non square residue in FP, factor out p-1 by powers of 2, find Q and S such that p − 1 = Q....
Definition: mphell-fp.c:104
void fp_str(char **str, const fp_param param, const uint8_t base, uint8_t stack)
Converts fp_param param to string format in base specified by base.
Definition: mphell-fp.c:543
int8_t fp_elt_ispower_number(fp_elt_srcptr src, number_srcptr n, const fp_param param, uint8_t stack)
Test if src is a n-power in Fp.
Definition: mphell-fp.c:909
void number_lshift(number_ptr dst, number_srcptr src, const uint16_t shift)
Set dst to src << shift.
void fp_elt_set_number(fp_elt_ptr dst, number_srcptr src, const bool isreduced, const fp_param param, uint8_t stack)
Set dst to src, if Montgomery arithmetic is used, is_reduced == false -> transform dst into its Montg...
Definition: mphell-fp.c:433
bool fp_elt_isone(fp_elt_srcptr src, const fp_param param)
Test if src is one.
Definition: mphell-fp.c:654
void fp_elt_get_number(number_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
If Montgomery arithmetic is used, lift src (which is into Montgomery form) to classical number (in FP...
Definition: mphell-fp.c:522
void number_gcd_ui(block *dst, number_srcptr src1, const block src2)
Set dst to GCD(src1, src2)
static void fp_elt_mul(fp_elt_ptr dst, fp_elt_srcptr src1, fp_elt_srcptr src2, const fp_param param, uint8_t stack)
Set dst <- src1 * src2, if Montgomery arithmetic is used, the Montgomery multiplication will be used ...
Definition: mphell-fp.h:643
static bool fp_elt_iszero(fp_elt_srcptr src, const fp_param param)
Test if src is zero.
Definition: mphell-fp.h:462
block number_and_ui(number_srcptr src1, const block src2, uint8_t stack)
Apply logical bitwise AND operator between src1 and src2.
static void fp_elt_get_pool_elt(fp_elt *dst, const fp_param param, uint8_t stack)
Get an initialised field element from the pool.
Definition: mphell-fp.h:158
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 fp_elt_alloc(fp_elt *dst, const fp_param param)
Allocate space for a primary field element.
Definition: mphell-fp.c:344
void fp_elt_inv(fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
Set dst <- src^(-1)
Definition: mphell-fp.c:716
static void fp_elt_neg(fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param)
Set dst <- (-src) mod p.
Definition: mphell-fp.h:613
void fp_elt_set_zero(fp_elt_ptr dst, const fp_param param)
Set dst to zero.
Definition: mphell-fp.c:404
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 fp_copy(fp_param param_res, const fp_param param)
Copy the prime field structure param into param_res.
Definition: mphell-fp.c:266
void fp_elt_div(fp_elt_ptr dst, fp_elt_srcptr src1, fp_elt_srcptr src2, const fp_param param, uint8_t stack)
Set dst <- src1 / src2.
Definition: mphell-fp.c:740
void number_dec(number_ptr dst, number_srcptr src)
Set dst to src - 1 if src - 1 fit in dst.
int8_t fp_elt_ispower_ui(fp_elt_srcptr src, const block n, const fp_param param, uint8_t stack)
Test if src is a n-power in Fp.
Definition: mphell-fp.c:865
void number_inc(number_ptr dst, number_srcptr src)
Set dst to src + 1 if src + 1 fit in dst.
void fp_elt_set_str(fp_elt_ptr dst, const char *str, const uint8_t base, const bool isreduced, const fp_param param, uint8_t stack)
Set dst to str, if Montgomery arithmetic is used, is_reduced == false -> transform dst into its Montg...
Definition: mphell-fp.c:455
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
int8_t number_cmp(number_srcptr src1, number_srcptr src2)
Compare src1 and src2.
void fp_elt_unity_nth_root(fp_elt_ptr dst, const block n, const fp_param param, uint8_t stack)
Set dst to a non trivial n-th root of unity if it exists (ie n divides p-1), 1 otherwise.
Definition: mphell-fp.c:1257
Declaration of primary field functions, if Montgomery arithmetic is used, the Montgomery arithmetic w...
void fp_elt_print(fp_elt_srcptr src, const uint8_t base, const bool lift, const fp_param param, uint8_t stack)
Print src in base "base".
Definition: mphell-fp.c:40
void number_mod(number_ptr dst, number_srcptr src1, number_srcptr src2)
Compute dst such that src1 = q * src2 + dst ; dst < src2.
void fp_elt_cube_root(fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
Set dst <- src^(1/3) mod p.
Definition: mphell-fp.c:1019
void fp_elt_lift(fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
If Montgomery arithmetic is used, lift src (which is into Montgomery form) to classical fp.
Definition: mphell-fp.c:503
void number_rshift(number_ptr dst, number_srcptr src, const uint16_t shift)
Set dst to src >> shift.
Primary field parameters.
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(...
bool fp_elt_issquare(fp_elt_srcptr src, const fp_param param, uint8_t stack)
Test if src is a square using the Lengendre symbol.
Definition: mphell-fp.c:848
void fp_elt_primitive_elt(fp_elt_ptr dst, const fp_param param, uint8_t stack)
Find a possible primitive element in the field defined by param.
Definition: mphell-fp.c:1199
void fp_elt_sqrt(fp_elt_ptr dst, fp_elt_srcptr src, const fp_param param, uint8_t stack)
Set dst <- src^(1/2) mod p, using Tonelli–Shanks algorithm.
Definition: mphell-fp.c:956
void fp_elt_random(fp_elt_ptr dst, const fp_param param, uint8_t stack)
Set dst to a random element of Fp, the random process is chosen at the MHELL initialisation.
Definition: mphell-fp.c:481
void number_inv_mod_basis(block *dst, const block src)
Compute dst such that dst * (-src) = -1 mod (2^(BLOCK_SIZE))
int8_t number_cmp_ui(number_srcptr src1, const block src2)
Compare src1 and src2.
void fp_alloc(fp_param param, const uint8_t size)
Allocate space for the prime field informations structure.
Definition: mphell-fp.c:58
void fp_elt_set_one(fp_elt_ptr dst, const fp_param param)
Set dst to one (or its Montgomery form if Montgomery arithmetic is used)
Definition: mphell-fp.c:394
void fp_elt_str(char **str, fp_elt_srcptr src, const uint8_t base, const bool lift, const fp_param param, uint8_t stack)
Converts src to string format in base specified by base.
Definition: mphell-fp.c:600
void number_str(char **str, number_srcptr src, const uint8_t base)
Converts src to string format in base specified by base.
void fp_elt_init(fp_elt_ptr dst, const fp_param param)
Initialise a primary field element.
Definition: mphell-fp.c:357