x25519_ref10.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include <stddef.h>
  2. #include <stdint.h>
  3. #include "../scalarmult_curve25519.h"
  4. #include "export.h"
  5. #include "private/ed25519_ref10.h"
  6. #include "utils.h"
  7. #include "x25519_ref10.h"
  8. /*
  9. * Reject small order points early to mitigate the implications of
  10. * unexpected optimizations that would affect the ref10 code.
  11. * See https://eprint.iacr.org/2017/806.pdf for reference.
  12. */
  13. static int
  14. has_small_order(const unsigned char s[32])
  15. {
  16. CRYPTO_ALIGN(16)
  17. static const unsigned char blacklist[][32] = {
  18. /* 0 (order 4) */
  19. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  20. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  21. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  22. /* 1 (order 1) */
  23. { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  24. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  25. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  26. /* 325606250916557431795983626356110631294008115727848805560023387167927233504
  27. (order 8) */
  28. { 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
  29. 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
  30. 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 },
  31. /* 39382357235489614581723060781553021112529911719440698176882885853963445705823
  32. (order 8) */
  33. { 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1,
  34. 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c,
  35. 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 },
  36. /* p-1 (order 2) */
  37. { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  38. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  39. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
  40. /* p (=0, order 4) */
  41. { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  42. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  43. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
  44. /* p+1 (=1, order 1) */
  45. { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  46. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  47. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }
  48. };
  49. unsigned char c[7] = { 0 };
  50. unsigned int k;
  51. size_t i, j;
  52. COMPILER_ASSERT(7 == sizeof blacklist / sizeof blacklist[0]);
  53. for (j = 0; j < 31; j++) {
  54. for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
  55. c[i] |= s[j] ^ blacklist[i][j];
  56. }
  57. }
  58. for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
  59. c[i] |= (s[j] & 0x7f) ^ blacklist[i][j];
  60. }
  61. k = 0;
  62. for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
  63. k |= (c[i] - 1);
  64. }
  65. return (int) ((k >> 8) & 1);
  66. }
  67. static int
  68. crypto_scalarmult_curve25519_ref10(unsigned char *q,
  69. const unsigned char *n,
  70. const unsigned char *p)
  71. {
  72. unsigned char *t = q;
  73. unsigned int i;
  74. fe25519 x1;
  75. fe25519 x2;
  76. fe25519 z2;
  77. fe25519 x3;
  78. fe25519 z3;
  79. fe25519 tmp0;
  80. fe25519 tmp1;
  81. int pos;
  82. unsigned int swap;
  83. unsigned int b;
  84. if (has_small_order(p)) {
  85. return -1;
  86. }
  87. for (i = 0; i < 32; i++) {
  88. t[i] = n[i];
  89. }
  90. t[0] &= 248;
  91. t[31] &= 127;
  92. t[31] |= 64;
  93. fe25519_frombytes(x1, p);
  94. fe25519_1(x2);
  95. fe25519_0(z2);
  96. fe25519_copy(x3, x1);
  97. fe25519_1(z3);
  98. swap = 0;
  99. for (pos = 254; pos >= 0; --pos) {
  100. b = t[pos / 8] >> (pos & 7);
  101. b &= 1;
  102. swap ^= b;
  103. fe25519_cswap(x2, x3, swap);
  104. fe25519_cswap(z2, z3, swap);
  105. swap = b;
  106. fe25519_sub(tmp0, x3, z3);
  107. fe25519_sub(tmp1, x2, z2);
  108. fe25519_add(x2, x2, z2);
  109. fe25519_add(z2, x3, z3);
  110. fe25519_mul(z3, tmp0, x2);
  111. fe25519_mul(z2, z2, tmp1);
  112. fe25519_sq(tmp0, tmp1);
  113. fe25519_sq(tmp1, x2);
  114. fe25519_add(x3, z3, z2);
  115. fe25519_sub(z2, z3, z2);
  116. fe25519_mul(x2, tmp1, tmp0);
  117. fe25519_sub(tmp1, tmp1, tmp0);
  118. fe25519_sq(z2, z2);
  119. fe25519_mul32(z3, tmp1, 121666);
  120. fe25519_sq(x3, x3);
  121. fe25519_add(tmp0, tmp0, z3);
  122. fe25519_mul(z3, x1, z2);
  123. fe25519_mul(z2, tmp1, tmp0);
  124. }
  125. fe25519_cswap(x2, x3, swap);
  126. fe25519_cswap(z2, z3, swap);
  127. fe25519_invert(z2, z2);
  128. fe25519_mul(x2, x2, z2);
  129. fe25519_tobytes(q, x2);
  130. return 0;
  131. }
  132. static void
  133. edwards_to_montgomery(fe25519 montgomeryX, const fe25519 edwardsY, const fe25519 edwardsZ)
  134. {
  135. fe25519 tempX;
  136. fe25519 tempZ;
  137. fe25519_add(tempX, edwardsZ, edwardsY);
  138. fe25519_sub(tempZ, edwardsZ, edwardsY);
  139. fe25519_invert(tempZ, tempZ);
  140. fe25519_mul(montgomeryX, tempX, tempZ);
  141. }
  142. static int
  143. crypto_scalarmult_curve25519_ref10_base(unsigned char *q,
  144. const unsigned char *n)
  145. {
  146. unsigned char *t = q;
  147. ge25519_p3 A;
  148. fe25519 pk;
  149. unsigned int i;
  150. for (i = 0; i < 32; i++) {
  151. t[i] = n[i];
  152. }
  153. t[0] &= 248;
  154. t[31] &= 127;
  155. t[31] |= 64;
  156. ge25519_scalarmult_base(&A, t);
  157. edwards_to_montgomery(pk, A.Y, A.Z);
  158. fe25519_tobytes(q, pk);
  159. return 0;
  160. }
  161. struct crypto_scalarmult_curve25519_implementation
  162. crypto_scalarmult_curve25519_ref10_implementation = {
  163. SODIUM_C99(.mult =) crypto_scalarmult_curve25519_ref10,
  164. SODIUM_C99(.mult_base =) crypto_scalarmult_curve25519_ref10_base
  165. };