You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

205 lines
5.5 KiB

  1. /**
  2. * @file curve25519/elligator.c
  3. * @author Mike Hamburg
  4. *
  5. * @copyright
  6. * Copyright (c) 2015-2016 Cryptography Research, Inc. \n
  7. * Released under the MIT License. See LICENSE.txt for license information.
  8. *
  9. * @brief Elligator high-level functions.
  10. *
  11. * @warning This file was automatically generated in Python.
  12. * Please do not edit it.
  13. */
  14. #include "word.h"
  15. #include "field.h"
  16. #include <decaf.h>
  17. /* Template stuff */
  18. #define API_NS(_id) decaf_255_##_id
  19. #define point_t API_NS(point_t)
  20. #define IMAGINE_TWIST 1
  21. #define COFACTOR 8
  22. static const int EDWARDS_D = -121665;
  23. #define RISTRETTO_FACTOR DECAF_255_RISTRETTO_FACTOR
  24. extern const gf RISTRETTO_FACTOR;
  25. /* End of template stuff */
  26. extern mask_t API_NS(deisogenize) (
  27. gf_s *__restrict__ s,
  28. gf_s *__restrict__ inv_el_sum,
  29. gf_s *__restrict__ inv_el_m1,
  30. const point_t p,
  31. mask_t toggle_hibit_s,
  32. mask_t toggle_altx,
  33. mask_t toggle_rotation
  34. );
  35. void API_NS(point_from_hash_nonuniform) (
  36. point_t p,
  37. const unsigned char ser[SER_BYTES]
  38. ) {
  39. gf r0,r,a,b,c,N,e;
  40. const uint8_t mask = (uint8_t)(0xFE<<(6));
  41. ignore_result(gf_deserialize(r0,ser,0,mask));
  42. gf_strong_reduce(r0);
  43. gf_sqr(a,r0);
  44. gf_mul_qnr(r,a);
  45. /* Compute D@c := (dr+a-d)(dr-ar-d) with a=1 */
  46. gf_sub(a,r,ONE);
  47. gf_mulw(b,a,EDWARDS_D); /* dr-d */
  48. gf_add(a,b,ONE);
  49. gf_sub(b,b,r);
  50. gf_mul(c,a,b);
  51. /* compute N := (r+1)(a-2d) */
  52. gf_add(a,r,ONE);
  53. gf_mulw(N,a,1-2*EDWARDS_D);
  54. /* e = +-sqrt(1/ND) or +-r0 * sqrt(qnr/ND) */
  55. gf_mul(a,c,N);
  56. mask_t square = gf_isr(b,a);
  57. gf_cond_sel(c,r0,ONE,square); /* r? = square ? 1 : r0 */
  58. gf_mul(e,b,c);
  59. /* s@a = +-|N.e| */
  60. gf_mul(a,N,e);
  61. gf_cond_neg(a,gf_lobit(a) ^ ~square);
  62. /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */
  63. gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */
  64. gf_sqr(b,c);
  65. gf_sub(e,r,ONE);
  66. gf_mul(c,b,e);
  67. gf_mul(b,c,N);
  68. gf_cond_neg(b,square);
  69. gf_sub(b,b,ONE);
  70. /* isogenize */
  71. #if IMAGINE_TWIST
  72. gf_mul(c,a,SQRT_MINUS_ONE);
  73. gf_copy(a,c);
  74. #endif
  75. gf_sqr(c,a); /* s^2 */
  76. gf_add(a,a,a); /* 2s */
  77. gf_add(e,c,ONE);
  78. gf_mul(p->t,a,e); /* 2s(1+s^2) */
  79. gf_mul(p->x,a,b); /* 2st */
  80. gf_sub(a,ONE,c);
  81. gf_mul(p->y,e,a); /* (1+s^2)(1-s^2) */
  82. gf_mul(p->z,a,b); /* (1-s^2)t */
  83. assert(API_NS(point_valid)(p));
  84. }
  85. void API_NS(point_from_hash_uniform) (
  86. point_t pt,
  87. const unsigned char hashed_data[2*SER_BYTES]
  88. ) {
  89. point_t pt2;
  90. API_NS(point_from_hash_nonuniform)(pt,hashed_data);
  91. API_NS(point_from_hash_nonuniform)(pt2,&hashed_data[SER_BYTES]);
  92. API_NS(point_add)(pt,pt,pt2);
  93. }
  94. /* Elligator_onto:
  95. * Make elligator-inverse onto at the cost of roughly halving the success probability.
  96. * Currently no effect for curves with field size 1 bit mod 8 (where the top bit
  97. * is chopped off). FUTURE MAGIC: automatic at least for brainpool-style curves; support
  98. * log p == 1 mod 8 brainpool curves maybe?
  99. */
  100. #define MAX(A,B) (((A)>(B)) ? (A) : (B))
  101. decaf_error_t
  102. API_NS(invert_elligator_nonuniform) (
  103. unsigned char recovered_hash[SER_BYTES],
  104. const point_t p,
  105. uint32_t hint_
  106. ) {
  107. mask_t hint = hint_;
  108. mask_t sgn_s = -(hint & 1),
  109. sgn_altx = -(hint>>1 & 1),
  110. sgn_r0 = -(hint>>2 & 1),
  111. /* FUTURE MAGIC: eventually if there's a curve which needs sgn_ed_T but not sgn_r0,
  112. * change this mask extraction.
  113. */
  114. sgn_ed_T = -(hint>>3 & 1);
  115. gf a,b,c;
  116. API_NS(deisogenize)(a,b,c,p,sgn_s,sgn_altx,sgn_ed_T);
  117. mask_t is_identity = gf_eq(p->t,ZERO);
  118. #if COFACTOR==4
  119. gf_cond_sel(b,b,ONE,is_identity & sgn_altx);
  120. gf_cond_sel(c,c,ONE,is_identity & sgn_s &~ sgn_altx);
  121. #elif IMAGINE_TWIST
  122. /* Terrible, terrible special casing due to lots of 0/0 is deisogenize
  123. * Basically we need to generate -D and +- i*RISTRETTO_FACTOR
  124. */
  125. gf_mul_i(a,RISTRETTO_FACTOR);
  126. gf_cond_sel(b,b,ONE,is_identity);
  127. gf_cond_neg(a,sgn_altx);
  128. gf_cond_sel(c,c,a,is_identity & sgn_ed_T);
  129. gf_cond_sel(c,c,ZERO,is_identity & ~sgn_ed_T);
  130. gf_mulw(a,ONE,-EDWARDS_D);
  131. gf_cond_sel(c,c,a,is_identity & ~sgn_ed_T &~ sgn_altx);
  132. #else
  133. #error "Different special-casing goes here!"
  134. #endif
  135. #if IMAGINE_TWIST
  136. gf_mulw(a,b,-EDWARDS_D);
  137. #else
  138. gf_mulw(a,b,EDWARDS_D-1);
  139. #endif
  140. gf_add(b,a,b);
  141. gf_sub(a,a,c);
  142. gf_add(b,b,c);
  143. gf_cond_swap(a,b,sgn_s);
  144. gf_mul_qnr(c,b);
  145. gf_mul(b,c,a);
  146. mask_t succ = gf_isr(c,b);
  147. succ |= gf_eq(b,ZERO);
  148. gf_mul(b,c,a);
  149. #if 255 == 8*SER_BYTES + 1 /* p521. */
  150. #error "this won't work because it needs to adjust high bit, not low bit"
  151. sgn_r0 = 0;
  152. #endif
  153. gf_cond_neg(b, sgn_r0^gf_lobit(b));
  154. /* Eliminate duplicate values for identity ... */
  155. succ &= ~(gf_eq(b,ZERO) & (sgn_r0 | sgn_s));
  156. // #if COFACTOR == 8
  157. // succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */
  158. // #endif
  159. #if 255 == 8*SER_BYTES + 1 /* p521 */
  160. gf_serialize(recovered_hash,b,0);
  161. #else
  162. gf_serialize(recovered_hash,b,1);
  163. #endif
  164. #if 7
  165. #if COFACTOR==8
  166. recovered_hash[SER_BYTES-1] ^= (hint>>4)<<7;
  167. #else
  168. recovered_hash[SER_BYTES-1] ^= (hint>>3)<<7;
  169. #endif
  170. #endif
  171. return decaf_succeed_if(mask_to_bool(succ));
  172. }
  173. decaf_error_t
  174. API_NS(invert_elligator_uniform) (
  175. unsigned char partial_hash[2*SER_BYTES],
  176. const point_t p,
  177. uint32_t hint
  178. ) {
  179. point_t pt2;
  180. API_NS(point_from_hash_nonuniform)(pt2,&partial_hash[SER_BYTES]);
  181. API_NS(point_sub)(pt2,p,pt2);
  182. return API_NS(invert_elligator_nonuniform)(partial_hash,pt2,hint);
  183. }