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.
 
 
 
 
 

200 lines
5.8 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. /* End of template stuff */
  24. extern void API_NS(deisogenize) (
  25. gf_s *__restrict__ s,
  26. gf_s *__restrict__ minus_t_over_s,
  27. const point_t p,
  28. mask_t toggle_hibit_s,
  29. mask_t toggle_hibit_t_over_s,
  30. mask_t toggle_rotation
  31. );
  32. void API_NS(point_from_hash_nonuniform) (
  33. point_t p,
  34. const unsigned char ser[SER_BYTES]
  35. ) {
  36. gf r0,r,a,b,c,N,e;
  37. ignore_result(gf_deserialize(r0,ser,0));
  38. gf_strong_reduce(r0);
  39. gf_sqr(a,r0);
  40. gf_mul_qnr(r,a);
  41. /* Compute D@c := (dr+a-d)(dr-ar-d) with a=1 */
  42. gf_sub(a,r,ONE);
  43. gf_mulw(b,a,EDWARDS_D); /* dr-d */
  44. gf_add(a,b,ONE);
  45. gf_sub(b,b,r);
  46. gf_mul(c,a,b);
  47. /* compute N := (r+1)(a-2d) */
  48. gf_add(a,r,ONE);
  49. gf_mulw(N,a,1-2*EDWARDS_D);
  50. /* e = +-sqrt(1/ND) or +-r0 * sqrt(qnr/ND) */
  51. gf_mul(a,c,N);
  52. mask_t square = gf_isr(b,a);
  53. gf_cond_sel(c,r0,ONE,square); /* r? = square ? 1 : r0 */
  54. gf_mul(e,b,c);
  55. /* s@a = +-|N.e| */
  56. gf_mul(a,N,e);
  57. gf_cond_neg(a,gf_hibit(a)^square); /* NB this is - what is listen in the paper */
  58. /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */
  59. gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */
  60. gf_sqr(b,c);
  61. gf_sub(e,r,ONE);
  62. gf_mul(c,b,e);
  63. gf_mul(b,c,N);
  64. gf_cond_neg(b,square);
  65. gf_sub(b,b,ONE);
  66. /* isogenize */
  67. #if IMAGINE_TWIST
  68. gf_mul(c,a,SQRT_MINUS_ONE);
  69. gf_copy(a,c);
  70. #endif
  71. gf_sqr(c,a); /* s^2 */
  72. gf_add(a,a,a); /* 2s */
  73. gf_add(e,c,ONE);
  74. gf_mul(p->t,a,e); /* 2s(1+s^2) */
  75. gf_mul(p->x,a,b); /* 2st */
  76. gf_sub(a,ONE,c);
  77. gf_mul(p->y,e,a); /* (1+s^2)(1-s^2) */
  78. gf_mul(p->z,a,b); /* (1-s^2)t */
  79. assert(API_NS(point_valid)(p));
  80. }
  81. void API_NS(point_from_hash_uniform) (
  82. point_t pt,
  83. const unsigned char hashed_data[2*SER_BYTES]
  84. ) {
  85. point_t pt2;
  86. API_NS(point_from_hash_nonuniform)(pt,hashed_data);
  87. API_NS(point_from_hash_nonuniform)(pt2,&hashed_data[SER_BYTES]);
  88. API_NS(point_add)(pt,pt,pt2);
  89. }
  90. /* Elligator_onto:
  91. * Make elligator-inverse onto at the cost of roughly halving the success probability.
  92. * Currently no effect for curves with field size 1 bit mod 8 (where the top bit
  93. * is chopped off). FUTURE MAGIC: automatic at least for brainpool-style curves; support
  94. * log p == 1 mod 8 brainpool curves maybe?
  95. */
  96. #define MAX(A,B) (((A)>(B)) ? (A) : (B))
  97. #define PKP_MASK ((1<<(MAX(8*SER_BYTES + 0 - 255,0)))-1)
  98. #if PKP_MASK != 0
  99. static UNUSED mask_t plus_k_p (
  100. uint8_t x[SER_BYTES],
  101. uint32_t factor_
  102. ) {
  103. uint32_t carry = 0;
  104. uint64_t factor = factor_;
  105. const uint8_t p[SER_BYTES] = { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f };
  106. for (unsigned int i=0; i<SER_BYTES; i++) {
  107. uint64_t tmp = carry + p[i] * factor + x[i];
  108. /* tmp <= 2^32-1 + (2^32-1)*(2^8-1) + (2^8-1) = 2^40-1 */
  109. x[i] = tmp; carry = tmp>>8;
  110. }
  111. return word_is_zero(carry);
  112. }
  113. #endif
  114. decaf_error_t
  115. API_NS(invert_elligator_nonuniform) (
  116. unsigned char recovered_hash[SER_BYTES],
  117. const point_t p,
  118. uint32_t hint_
  119. ) {
  120. mask_t hint = hint_;
  121. mask_t sgn_s = -(hint & 1),
  122. sgn_t_over_s = -(hint>>1 & 1),
  123. sgn_r0 = -(hint>>2 & 1),
  124. /* FUTURE MAGIC: eventually if there's a curve which needs sgn_ed_T but not sgn_r0,
  125. * change this mask extraction.
  126. */
  127. sgn_ed_T = -(hint>>3 & 1);
  128. gf a, b, c, d;
  129. API_NS(deisogenize)(a,c,p,sgn_s,sgn_t_over_s,sgn_ed_T);
  130. #if 255 == 8*SER_BYTES + 1 /* p521. */
  131. sgn_r0 = 0;
  132. #endif
  133. /* ok, a = s; c = -t/s */
  134. gf_mul(b,c,a);
  135. gf_sub(b,ONE,b); /* t+1 */
  136. gf_sqr(c,a); /* s^2 */
  137. mask_t is_identity = gf_eq(p->t,ZERO);
  138. /* identity adjustments */
  139. /* in case of identity, currently c=0, t=0, b=1, will encode to 1 */
  140. /* if hint is 0, -> 0 */
  141. /* if hint is to neg t/s, then go to infinity, effectively set s to 1 */
  142. gf_cond_sel(c,c,ONE,is_identity & sgn_t_over_s);
  143. gf_cond_sel(b,b,ZERO,is_identity & ~sgn_t_over_s & ~sgn_s);
  144. gf_mulw(d,c,2*EDWARDS_D-1); /* $d = (2d-a)s^2 */
  145. gf_add(a,b,d); /* num? */
  146. gf_sub(d,d,b); /* den? */
  147. gf_mul(b,a,d); /* n*d */
  148. gf_cond_sel(a,d,a,sgn_s);
  149. gf_mul_qnr(d,b);
  150. mask_t succ = gf_isr(c,d)|gf_eq(d,ZERO);
  151. gf_mul(b,a,c);
  152. gf_cond_neg(b, sgn_r0^gf_hibit(b));
  153. succ &= ~(gf_eq(b,ZERO) & sgn_r0);
  154. #if COFACTOR == 8
  155. succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */
  156. #endif
  157. #if 255 == 8*SER_BYTES + 1 /* p521 */
  158. gf_serialize(recovered_hash,b,0);
  159. #else
  160. gf_serialize(recovered_hash,b,1);
  161. #if PKP_MASK != 0
  162. /* Add a multiple of p to make the result either almost-onto or completely onto. */
  163. succ &= plus_k_p(recovered_hash, (hint >> ((COFACTOR==8)?4:3)) & PKP_MASK);
  164. #endif
  165. #endif
  166. return decaf_succeed_if(mask_to_bool(succ));
  167. }
  168. decaf_error_t
  169. API_NS(invert_elligator_uniform) (
  170. unsigned char partial_hash[2*SER_BYTES],
  171. const point_t p,
  172. uint32_t hint
  173. ) {
  174. point_t pt2;
  175. API_NS(point_from_hash_nonuniform)(pt2,&partial_hash[SER_BYTES]);
  176. API_NS(point_sub)(pt2,p,pt2);
  177. return API_NS(invert_elligator_nonuniform)(partial_hash,pt2,hint);
  178. }