fe_tobytes.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #include "fe.h"
  2. /*
  3. Preconditions:
  4. |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
  5. Write p=2^255-19; q=floor(h/p).
  6. Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
  7. Proof:
  8. Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
  9. Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
  10. Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
  11. Then 0<y<1.
  12. Write r=h-pq.
  13. Have 0<=r<=p-1=2^255-20.
  14. Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
  15. Write x=r+19(2^-255)r+y.
  16. Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
  17. Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
  18. so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
  19. */
  20. void fe_tobytes(unsigned char *s,const fe h)
  21. {
  22. crypto_int32 h0 = h[0];
  23. crypto_int32 h1 = h[1];
  24. crypto_int32 h2 = h[2];
  25. crypto_int32 h3 = h[3];
  26. crypto_int32 h4 = h[4];
  27. crypto_int32 h5 = h[5];
  28. crypto_int32 h6 = h[6];
  29. crypto_int32 h7 = h[7];
  30. crypto_int32 h8 = h[8];
  31. crypto_int32 h9 = h[9];
  32. crypto_int32 q;
  33. crypto_int32 carry0;
  34. crypto_int32 carry1;
  35. crypto_int32 carry2;
  36. crypto_int32 carry3;
  37. crypto_int32 carry4;
  38. crypto_int32 carry5;
  39. crypto_int32 carry6;
  40. crypto_int32 carry7;
  41. crypto_int32 carry8;
  42. crypto_int32 carry9;
  43. q = (19 * h9 + (((crypto_int32) 1) << 24)) >> 25;
  44. q = (h0 + q) >> 26;
  45. q = (h1 + q) >> 25;
  46. q = (h2 + q) >> 26;
  47. q = (h3 + q) >> 25;
  48. q = (h4 + q) >> 26;
  49. q = (h5 + q) >> 25;
  50. q = (h6 + q) >> 26;
  51. q = (h7 + q) >> 25;
  52. q = (h8 + q) >> 26;
  53. q = (h9 + q) >> 25;
  54. /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
  55. h0 += 19 * q;
  56. /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
  57. carry0 = h0 >> 26; h1 += carry0; h0 -= SHL32(carry0,26);
  58. carry1 = h1 >> 25; h2 += carry1; h1 -= SHL32(carry1,25);
  59. carry2 = h2 >> 26; h3 += carry2; h2 -= SHL32(carry2,26);
  60. carry3 = h3 >> 25; h4 += carry3; h3 -= SHL32(carry3,25);
  61. carry4 = h4 >> 26; h5 += carry4; h4 -= SHL32(carry4,26);
  62. carry5 = h5 >> 25; h6 += carry5; h5 -= SHL32(carry5,25);
  63. carry6 = h6 >> 26; h7 += carry6; h6 -= SHL32(carry6,26);
  64. carry7 = h7 >> 25; h8 += carry7; h7 -= SHL32(carry7,25);
  65. carry8 = h8 >> 26; h9 += carry8; h8 -= SHL32(carry8,26);
  66. carry9 = h9 >> 25; h9 -= SHL32(carry9,25);
  67. /* h10 = carry9 */
  68. /*
  69. Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
  70. Have h0+...+2^230 h9 between 0 and 2^255-1;
  71. evidently 2^255 h10-2^255 q = 0.
  72. Goal: Output h0+...+2^230 h9.
  73. */
  74. s[0] = h0 >> 0;
  75. s[1] = h0 >> 8;
  76. s[2] = h0 >> 16;
  77. s[3] = (h0 >> 24) | SHL32(h1,2);
  78. s[4] = h1 >> 6;
  79. s[5] = h1 >> 14;
  80. s[6] = (h1 >> 22) | SHL32(h2,3);
  81. s[7] = h2 >> 5;
  82. s[8] = h2 >> 13;
  83. s[9] = (h2 >> 21) | SHL32(h3,5);
  84. s[10] = h3 >> 3;
  85. s[11] = h3 >> 11;
  86. s[12] = (h3 >> 19) | SHL32(h4,6);
  87. s[13] = h4 >> 2;
  88. s[14] = h4 >> 10;
  89. s[15] = h4 >> 18;
  90. s[16] = h5 >> 0;
  91. s[17] = h5 >> 8;
  92. s[18] = h5 >> 16;
  93. s[19] = (h5 >> 24) | SHL32(h6,1);
  94. s[20] = h6 >> 7;
  95. s[21] = h6 >> 15;
  96. s[22] = (h6 >> 23) | SHL32(h7,3);
  97. s[23] = h7 >> 5;
  98. s[24] = h7 >> 13;
  99. s[25] = (h7 >> 21) | SHL32(h8,4);
  100. s[26] = h8 >> 4;
  101. s[27] = h8 >> 12;
  102. s[28] = (h8 >> 20) | SHL32(h9,6);
  103. s[29] = h9 >> 2;
  104. s[30] = h9 >> 10;
  105. s[31] = h9 >> 18;
  106. }