x25519-x86_64.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #include <openssl/curve25519.h>
  2. #include <string.h>
  3. #include "internal.h"
  4. #if defined(BORINGSSL_X25519_X86_64)
  5. typedef struct { uint64_t v[5]; } fe25519;
  6. /* These functions are defined in asm/x25519-x86_64.S */
  7. void x25519_x86_64_work_cswap(fe25519 *, uint64_t);
  8. void x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b);
  9. void x25519_x86_64_square(fe25519 *out, const fe25519 *a);
  10. void x25519_x86_64_freeze(fe25519 *);
  11. void x25519_x86_64_ladderstep(fe25519 *work);
  12. static void fe25519_setint(fe25519 *r, unsigned v) {
  13. r->v[0] = v;
  14. r->v[1] = 0;
  15. r->v[2] = 0;
  16. r->v[3] = 0;
  17. r->v[4] = 0;
  18. }
  19. /* Assumes input x being reduced below 2^255 */
  20. static void fe25519_pack(unsigned char r[32], const fe25519 *x) {
  21. fe25519 t;
  22. t = *x;
  23. x25519_x86_64_freeze(&t);
  24. r[0] = (uint8_t)(t.v[0] & 0xff);
  25. r[1] = (uint8_t)((t.v[0] >> 8) & 0xff);
  26. r[2] = (uint8_t)((t.v[0] >> 16) & 0xff);
  27. r[3] = (uint8_t)((t.v[0] >> 24) & 0xff);
  28. r[4] = (uint8_t)((t.v[0] >> 32) & 0xff);
  29. r[5] = (uint8_t)((t.v[0] >> 40) & 0xff);
  30. r[6] = (uint8_t)((t.v[0] >> 48));
  31. r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8);
  32. r[7] = (uint8_t)((t.v[1] >> 5) & 0xff);
  33. r[8] = (uint8_t)((t.v[1] >> 13) & 0xff);
  34. r[9] = (uint8_t)((t.v[1] >> 21) & 0xff);
  35. r[10] = (uint8_t)((t.v[1] >> 29) & 0xff);
  36. r[11] = (uint8_t)((t.v[1] >> 37) & 0xff);
  37. r[12] = (uint8_t)((t.v[1] >> 45));
  38. r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0);
  39. r[13] = (uint8_t)((t.v[2] >> 2) & 0xff);
  40. r[14] = (uint8_t)((t.v[2] >> 10) & 0xff);
  41. r[15] = (uint8_t)((t.v[2] >> 18) & 0xff);
  42. r[16] = (uint8_t)((t.v[2] >> 26) & 0xff);
  43. r[17] = (uint8_t)((t.v[2] >> 34) & 0xff);
  44. r[18] = (uint8_t)((t.v[2] >> 42) & 0xff);
  45. r[19] = (uint8_t)((t.v[2] >> 50));
  46. r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe);
  47. r[20] = (uint8_t)((t.v[3] >> 7) & 0xff);
  48. r[21] = (uint8_t)((t.v[3] >> 15) & 0xff);
  49. r[22] = (uint8_t)((t.v[3] >> 23) & 0xff);
  50. r[23] = (uint8_t)((t.v[3] >> 31) & 0xff);
  51. r[24] = (uint8_t)((t.v[3] >> 39) & 0xff);
  52. r[25] = (uint8_t)((t.v[3] >> 47));
  53. r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0);
  54. r[26] = (uint8_t)((t.v[4] >> 4) & 0xff);
  55. r[27] = (uint8_t)((t.v[4] >> 12) & 0xff);
  56. r[28] = (uint8_t)((t.v[4] >> 20) & 0xff);
  57. r[29] = (uint8_t)((t.v[4] >> 28) & 0xff);
  58. r[30] = (uint8_t)((t.v[4] >> 36) & 0xff);
  59. r[31] = (uint8_t)((t.v[4] >> 44));
  60. }
  61. static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) {
  62. r->v[0] = x[0];
  63. r->v[0] += (uint64_t)x[1] << 8;
  64. r->v[0] += (uint64_t)x[2] << 16;
  65. r->v[0] += (uint64_t)x[3] << 24;
  66. r->v[0] += (uint64_t)x[4] << 32;
  67. r->v[0] += (uint64_t)x[5] << 40;
  68. r->v[0] += ((uint64_t)x[6] & 7) << 48;
  69. r->v[1] = x[6] >> 3;
  70. r->v[1] += (uint64_t)x[7] << 5;
  71. r->v[1] += (uint64_t)x[8] << 13;
  72. r->v[1] += (uint64_t)x[9] << 21;
  73. r->v[1] += (uint64_t)x[10] << 29;
  74. r->v[1] += (uint64_t)x[11] << 37;
  75. r->v[1] += ((uint64_t)x[12] & 63) << 45;
  76. r->v[2] = x[12] >> 6;
  77. r->v[2] += (uint64_t)x[13] << 2;
  78. r->v[2] += (uint64_t)x[14] << 10;
  79. r->v[2] += (uint64_t)x[15] << 18;
  80. r->v[2] += (uint64_t)x[16] << 26;
  81. r->v[2] += (uint64_t)x[17] << 34;
  82. r->v[2] += (uint64_t)x[18] << 42;
  83. r->v[2] += ((uint64_t)x[19] & 1) << 50;
  84. r->v[3] = x[19] >> 1;
  85. r->v[3] += (uint64_t)x[20] << 7;
  86. r->v[3] += (uint64_t)x[21] << 15;
  87. r->v[3] += (uint64_t)x[22] << 23;
  88. r->v[3] += (uint64_t)x[23] << 31;
  89. r->v[3] += (uint64_t)x[24] << 39;
  90. r->v[3] += ((uint64_t)x[25] & 15) << 47;
  91. r->v[4] = x[25] >> 4;
  92. r->v[4] += (uint64_t)x[26] << 4;
  93. r->v[4] += (uint64_t)x[27] << 12;
  94. r->v[4] += (uint64_t)x[28] << 20;
  95. r->v[4] += (uint64_t)x[29] << 28;
  96. r->v[4] += (uint64_t)x[30] << 36;
  97. r->v[4] += ((uint64_t)x[31] & 127) << 44;
  98. }
  99. static void fe25519_invert(fe25519 *r, const fe25519 *x) {
  100. fe25519 z2;
  101. fe25519 z9;
  102. fe25519 z11;
  103. fe25519 z2_5_0;
  104. fe25519 z2_10_0;
  105. fe25519 z2_20_0;
  106. fe25519 z2_50_0;
  107. fe25519 z2_100_0;
  108. fe25519 t;
  109. int i;
  110. /* 2 */ x25519_x86_64_square(&z2, x);
  111. /* 4 */ x25519_x86_64_square(&t, &z2);
  112. /* 8 */ x25519_x86_64_square(&t, &t);
  113. /* 9 */ x25519_x86_64_mul(&z9, &t, x);
  114. /* 11 */ x25519_x86_64_mul(&z11, &z9, &z2);
  115. /* 22 */ x25519_x86_64_square(&t, &z11);
  116. /* 2^5 - 2^0 = 31 */ x25519_x86_64_mul(&z2_5_0, &t, &z9);
  117. /* 2^6 - 2^1 */ x25519_x86_64_square(&t, &z2_5_0);
  118. /* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { x25519_x86_64_square(&t, &t); }
  119. /* 2^10 - 2^0 */ x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0);
  120. /* 2^11 - 2^1 */ x25519_x86_64_square(&t, &z2_10_0);
  121. /* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
  122. /* 2^20 - 2^0 */ x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0);
  123. /* 2^21 - 2^1 */ x25519_x86_64_square(&t, &z2_20_0);
  124. /* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { x25519_x86_64_square(&t, &t); }
  125. /* 2^40 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_20_0);
  126. /* 2^41 - 2^1 */ x25519_x86_64_square(&t, &t);
  127. /* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
  128. /* 2^50 - 2^0 */ x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0);
  129. /* 2^51 - 2^1 */ x25519_x86_64_square(&t, &z2_50_0);
  130. /* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
  131. /* 2^100 - 2^0 */ x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0);
  132. /* 2^101 - 2^1 */ x25519_x86_64_square(&t, &z2_100_0);
  133. /* 2^200 - 2^100 */ for (i = 1; i < 100; i++) {
  134. x25519_x86_64_square(&t, &t);
  135. }
  136. /* 2^200 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_100_0);
  137. /* 2^201 - 2^1 */ x25519_x86_64_square(&t, &t);
  138. /* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
  139. /* 2^250 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_50_0);
  140. /* 2^251 - 2^1 */ x25519_x86_64_square(&t, &t);
  141. /* 2^252 - 2^2 */ x25519_x86_64_square(&t, &t);
  142. /* 2^253 - 2^3 */ x25519_x86_64_square(&t, &t);
  143. /* 2^254 - 2^4 */ x25519_x86_64_square(&t, &t);
  144. /* 2^255 - 2^5 */ x25519_x86_64_square(&t, &t);
  145. /* 2^255 - 21 */ x25519_x86_64_mul(r, &t, &z11);
  146. }
  147. static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) {
  148. fe25519 work[5];
  149. work[0] = *xr;
  150. fe25519_setint(work + 1, 1);
  151. fe25519_setint(work + 2, 0);
  152. work[3] = *xr;
  153. fe25519_setint(work + 4, 1);
  154. int i, j;
  155. uint8_t prevbit = 0;
  156. j = 6;
  157. for (i = 31; i >= 0; i--) {
  158. while (j >= 0) {
  159. const uint8_t bit = 1 & (s[i] >> j);
  160. const uint64_t swap = bit ^ prevbit;
  161. prevbit = bit;
  162. x25519_x86_64_work_cswap(work + 1, swap);
  163. x25519_x86_64_ladderstep(work);
  164. j -= 1;
  165. }
  166. j = 7;
  167. }
  168. *xr = work[1];
  169. *zr = work[2];
  170. }
  171. void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
  172. const uint8_t point[32]) {
  173. uint8_t e[32];
  174. memcpy(e, scalar, sizeof(e));
  175. e[0] &= 248;
  176. e[31] &= 127;
  177. e[31] |= 64;
  178. fe25519 t;
  179. fe25519 z;
  180. fe25519_unpack(&t, point);
  181. mladder(&t, &z, e);
  182. fe25519_invert(&z, &z);
  183. x25519_x86_64_mul(&t, &t, &z);
  184. fe25519_pack(out, &t);
  185. }
  186. #endif /* BORINGSSL_X25519_X86_64 */