選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

345 行
12 KiB

  1. /********************************************************************************************
  2. * Supersingular Isogeny Key Encapsulation Library
  3. *
  4. * Abstract: ephemeral supersingular isogeny Diffie-Hellman key exchange (SIDH)
  5. *********************************************************************************************/
  6. #include "P751_internal.h"
  7. #include "random/random.h"
  8. #include <stdio.h>
  9. static void clear_words(void *mem, digit_t nwords)
  10. { // Clear digits from memory. "nwords" indicates the number of digits to be zeroed.
  11. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.
  12. unsigned int i;
  13. volatile digit_t *v = mem;
  14. for (i = 0; i < nwords; i++)
  15. {
  16. v[i] = 0;
  17. }
  18. }
  19. static void init_basis(digit_t *gen, f2elm_t XP, f2elm_t XQ, f2elm_t XR)
  20. { // Initialization of basis points
  21. fpcopy(gen, XP[0]);
  22. fpcopy(gen + NWORDS_FIELD, XP[1]);
  23. fpcopy(gen + 2 * NWORDS_FIELD, XQ[0]);
  24. fpzero(XQ[1]);
  25. fpcopy(gen + 3 * NWORDS_FIELD, XR[0]);
  26. fpcopy(gen + 4 * NWORDS_FIELD, XR[1]);
  27. }
  28. static void fp2_encode(const f2elm_t x, unsigned char *enc)
  29. { // Conversion of GF(p^2) element from Montgomery to standard representation, and encoding by removing leading 0 bytes
  30. unsigned int i;
  31. f2elm_t t;
  32. from_fp2mont(x, t);
  33. for (i = 0; i < FP2_ENCODED_BYTES / 2; i++)
  34. {
  35. enc[i] = ((unsigned char *)t)[i];
  36. enc[i + FP2_ENCODED_BYTES / 2] = ((unsigned char *)t)[i + MAXBITS_FIELD / 8];
  37. }
  38. }
  39. static void fp2_decode(const unsigned char *enc, f2elm_t x)
  40. { // Parse byte sequence back into GF(p^2) element, and conversion to Montgomery representation
  41. unsigned int i;
  42. for (i = 0; i < 2 * (MAXBITS_FIELD / 8); i++)
  43. ((unsigned char *)x)[i] = 0;
  44. for (i = 0; i < FP2_ENCODED_BYTES / 2; i++)
  45. {
  46. ((unsigned char *)x)[i] = enc[i];
  47. ((unsigned char *)x)[i + MAXBITS_FIELD / 8] = enc[i + FP2_ENCODED_BYTES / 2];
  48. }
  49. to_fp2mont(x, x);
  50. }
  51. void random_mod_order_A(unsigned char *random_digits)
  52. { // Generation of Alice's secret key
  53. // Outputs random value in [0, 2^eA - 1]
  54. unsigned long long nbytes = NBITS_TO_NBYTES(OALICE_BITS);
  55. clear_words((void *)random_digits, MAXWORDS_ORDER);
  56. randombytes(random_digits, nbytes);
  57. random_digits[nbytes - 1] &= MASK_ALICE; // Masking last byte
  58. }
  59. void random_mod_order_B(unsigned char *random_digits)
  60. { // Generation of Bob's secret key
  61. // Outputs random value in [0, 2^Floor(Log(2, oB)) - 1]
  62. unsigned long long nbytes = NBITS_TO_NBYTES(OBOB_BITS - 1);
  63. clear_words((void *)random_digits, MAXWORDS_ORDER);
  64. randombytes(random_digits, nbytes);
  65. random_digits[nbytes - 1] &= MASK_BOB; // Masking last byte
  66. }
  67. int EphemeralKeyGeneration_A(const unsigned char *PrivateKeyA, unsigned char *PublicKeyA)
  68. { // Alice's ephemeral public key generation
  69. // Input: a private key PrivateKeyA in the range [0, 2^eA - 1].
  70. // Output: the public key PublicKeyA consisting of 3 elements in GF(p^2) which are encoded by removing leading 0 bytes.
  71. point_proj_t R, phiP = {0}, phiQ = {0}, phiR = {0}, pts[MAX_INT_POINTS_ALICE];
  72. f2elm_t XPA, XQA, XRA, coeff[3], A24plus = {0}, C24 = {0}, A = {0};
  73. unsigned int i, row, m, index = 0, pts_index[MAX_INT_POINTS_ALICE], npts = 0, ii = 0;
  74. // Initialize basis points
  75. init_basis((digit_t *)A_gen, XPA, XQA, XRA);
  76. init_basis((digit_t *)B_gen, phiP->X, phiQ->X, phiR->X);
  77. fpcopy((digit_t *)&Montgomery_one, (phiP->Z)[0]);
  78. fpcopy((digit_t *)&Montgomery_one, (phiQ->Z)[0]);
  79. fpcopy((digit_t *)&Montgomery_one, (phiR->Z)[0]);
  80. // Initialize constants
  81. fpcopy((digit_t *)&Montgomery_one, A24plus[0]);
  82. fp2add(A24plus, A24plus, C24);
  83. uint64_t temp[12];
  84. uint64_t ifma_temp[15];
  85. // Retrieve kernel point
  86. LADDER3PT(XPA, XQA, XRA, (digit_t *)PrivateKeyA, ALICE, R, A);
  87. // Traverse tree
  88. index = 0;
  89. for (row = 1; row < MAX_Alice; row++)
  90. {
  91. while (index < MAX_Alice - row)
  92. {
  93. fp2copy(R->X, pts[npts]->X);
  94. fp2copy(R->Z, pts[npts]->Z);
  95. pts_index[npts++] = index;
  96. m = strat_Alice[ii++];
  97. xDBLe(R, R, A24plus, C24, (int)(2 * m));
  98. index += m;
  99. }
  100. get_4_isog(R, A24plus, C24, coeff);
  101. for (i = 0; i < npts; i++)
  102. {
  103. eval_4_isog(pts[i], coeff);
  104. }
  105. eval_4_isog(phiP, coeff);
  106. eval_4_isog(phiQ, coeff);
  107. eval_4_isog(phiR, coeff);
  108. fp2copy(pts[npts - 1]->X, R->X);
  109. fp2copy(pts[npts - 1]->Z, R->Z);
  110. index = pts_index[npts - 1];
  111. npts -= 1;
  112. }
  113. get_4_isog(R, A24plus, C24, coeff);
  114. eval_4_isog(phiP, coeff);
  115. eval_4_isog(phiQ, coeff);
  116. eval_4_isog(phiR, coeff);
  117. inv_3_way(phiP->Z, phiQ->Z, phiR->Z);
  118. fp2mul_mont(phiP->X, phiP->Z, phiP->X);
  119. fp2mul_mont(phiQ->X, phiQ->Z, phiQ->X);
  120. fp2mul_mont(phiR->X, phiR->Z, phiR->X);
  121. // Format public key
  122. fp2_encode(phiP->X, PublicKeyA);
  123. fp2_encode(phiQ->X, PublicKeyA + FP2_ENCODED_BYTES);
  124. fp2_encode(phiR->X, PublicKeyA + 2 * FP2_ENCODED_BYTES);
  125. return 0;
  126. }
  127. int EphemeralKeyGeneration_B(const unsigned char *PrivateKeyB, unsigned char *PublicKeyB)
  128. { // Bob's ephemeral public key generation
  129. // Input: a private key PrivateKeyB in the range [0, 2^Floor(Log(2,oB)) - 1].
  130. // Output: the public key PublicKeyB consisting of 3 elements in GF(p^2) which are encoded by removing leading 0 bytes.
  131. point_proj_t R, phiP = {0}, phiQ = {0}, phiR = {0}, pts[MAX_INT_POINTS_BOB];
  132. f2elm_t XPB, XQB, XRB, coeff[3], A24plus = {0}, A24minus = {0}, A = {0};
  133. unsigned int i, row, m, index = 0, pts_index[MAX_INT_POINTS_BOB], npts = 0, ii = 0;
  134. // Initialize basis points
  135. init_basis((digit_t *)B_gen, XPB, XQB, XRB);
  136. init_basis((digit_t *)A_gen, phiP->X, phiQ->X, phiR->X);
  137. fpcopy((digit_t *)&Montgomery_one, (phiP->Z)[0]);
  138. fpcopy((digit_t *)&Montgomery_one, (phiQ->Z)[0]);
  139. fpcopy((digit_t *)&Montgomery_one, (phiR->Z)[0]);
  140. // Initialize constants
  141. fpcopy((digit_t *)&Montgomery_one, A24plus[0]);
  142. fp2add(A24plus, A24plus, A24plus);
  143. fp2copy(A24plus, A24minus);
  144. fp2neg(A24minus);
  145. // Retrieve kernel point
  146. LADDER3PT(XPB, XQB, XRB, (digit_t *)PrivateKeyB, BOB, R, A);
  147. // Traverse tree
  148. index = 0;
  149. for (row = 1; row < MAX_Bob; row++)
  150. {
  151. while (index < MAX_Bob - row)
  152. {
  153. fp2copy(R->X, pts[npts]->X);
  154. fp2copy(R->Z, pts[npts]->Z);
  155. pts_index[npts++] = index;
  156. m = strat_Bob[ii++];
  157. xTPLe(R, R, A24minus, A24plus, (int)m);
  158. index += m;
  159. }
  160. get_3_isog(R, A24minus, A24plus, coeff);
  161. for (i = 0; i < npts; i++)
  162. {
  163. eval_3_isog(pts[i], coeff);
  164. }
  165. eval_3_isog(phiP, coeff);
  166. eval_3_isog(phiQ, coeff);
  167. eval_3_isog(phiR, coeff);
  168. fp2copy(pts[npts - 1]->X, R->X);
  169. fp2copy(pts[npts - 1]->Z, R->Z);
  170. index = pts_index[npts - 1];
  171. npts -= 1;
  172. }
  173. get_3_isog(R, A24minus, A24plus, coeff);
  174. eval_3_isog(phiP, coeff);
  175. eval_3_isog(phiQ, coeff);
  176. eval_3_isog(phiR, coeff);
  177. inv_3_way(phiP->Z, phiQ->Z, phiR->Z);
  178. fp2mul_mont(phiP->X, phiP->Z, phiP->X);
  179. fp2mul_mont(phiQ->X, phiQ->Z, phiQ->X);
  180. fp2mul_mont(phiR->X, phiR->Z, phiR->X);
  181. // Format public key
  182. fp2_encode(phiP->X, PublicKeyB);
  183. fp2_encode(phiQ->X, PublicKeyB + FP2_ENCODED_BYTES);
  184. fp2_encode(phiR->X, PublicKeyB + 2 * FP2_ENCODED_BYTES);
  185. return 0;
  186. }
  187. int EphemeralSecretAgreement_A(const unsigned char *PrivateKeyA, const unsigned char *PublicKeyB, unsigned char *SharedSecretA)
  188. { // Alice's ephemeral shared secret computation
  189. // It produces a shared secret key SharedSecretA using her secret key PrivateKeyA and Bob's public key PublicKeyB
  190. // Inputs: Alice's PrivateKeyA is an integer in the range [0, oA-1].
  191. // Bob's PublicKeyB consists of 3 elements in GF(p^2) encoded by removing leading 0 bytes.
  192. // Output: a shared secret SharedSecretA that consists of one element in GF(p^2) encoded by removing leading 0 bytes.
  193. point_proj_t R, pts[MAX_INT_POINTS_ALICE];
  194. f2elm_t coeff[3], PKB[3], jinv;
  195. f2elm_t A24plus = {0}, C24 = {0}, A = {0};
  196. unsigned int i, row, m, index = 0, pts_index[MAX_INT_POINTS_ALICE], npts = 0, ii = 0;
  197. // Initialize images of Bob's basis
  198. fp2_decode(PublicKeyB, PKB[0]);
  199. fp2_decode(PublicKeyB + FP2_ENCODED_BYTES, PKB[1]);
  200. fp2_decode(PublicKeyB + 2 * FP2_ENCODED_BYTES, PKB[2]);
  201. // Initialize constants
  202. get_A(PKB[0], PKB[1], PKB[2], A); // TODO: Can return projective A?
  203. fpadd((digit_t *)&Montgomery_one, (digit_t *)&Montgomery_one, C24[0]);
  204. fp2add(A, C24, A24plus);
  205. fpadd(C24[0], C24[0], C24[0]);
  206. // Retrieve kernel point
  207. LADDER3PT(PKB[0], PKB[1], PKB[2], (digit_t *)PrivateKeyA, ALICE, R, A);
  208. // Traverse tree
  209. index = 0;
  210. for (row = 1; row < MAX_Alice; row++)
  211. {
  212. while (index < MAX_Alice - row)
  213. {
  214. fp2copy(R->X, pts[npts]->X);
  215. fp2copy(R->Z, pts[npts]->Z);
  216. pts_index[npts++] = index;
  217. m = strat_Alice[ii++];
  218. xDBLe(R, R, A24plus, C24, (int)(2 * m));
  219. index += m;
  220. }
  221. get_4_isog(R, A24plus, C24, coeff);
  222. for (i = 0; i < npts; i++)
  223. {
  224. eval_4_isog(pts[i], coeff);
  225. }
  226. fp2copy(pts[npts - 1]->X, R->X);
  227. fp2copy(pts[npts - 1]->Z, R->Z);
  228. index = pts_index[npts - 1];
  229. npts -= 1;
  230. }
  231. get_4_isog(R, A24plus, C24, coeff);
  232. fp2div2(C24, C24);
  233. fp2sub(A24plus, C24, A24plus);
  234. fp2div2(C24, C24);
  235. j_inv(A24plus, C24, jinv);
  236. fp2_encode(jinv, SharedSecretA); // Format shared secret
  237. return 0;
  238. }
  239. int EphemeralSecretAgreement_B(const unsigned char *PrivateKeyB, const unsigned char *PublicKeyA, unsigned char *SharedSecretB)
  240. { // Bob's ephemeral shared secret computation
  241. // It produces a shared secret key SharedSecretB using his secret key PrivateKeyB and Alice's public key PublicKeyA
  242. // Inputs: Bob's PrivateKeyB is an integer in the range [0, 2^Floor(Log(2,oB)) - 1].
  243. // Alice's PublicKeyA consists of 3 elements in GF(p^2) encoded by removing leading 0 bytes.
  244. // Output: a shared secret SharedSecretB that consists of one element in GF(p^2) encoded by removing leading 0 bytes.
  245. point_proj_t R, pts[MAX_INT_POINTS_BOB];
  246. f2elm_t coeff[3], PKB[3], jinv;
  247. f2elm_t A24plus = {0}, A24minus = {0}, A = {0};
  248. unsigned int i, row, m, index = 0, pts_index[MAX_INT_POINTS_BOB], npts = 0, ii = 0;
  249. // Initialize images of Alice's basis
  250. fp2_decode(PublicKeyA, PKB[0]);
  251. fp2_decode(PublicKeyA + FP2_ENCODED_BYTES, PKB[1]);
  252. fp2_decode(PublicKeyA + 2 * FP2_ENCODED_BYTES, PKB[2]);
  253. // Initialize constants
  254. get_A(PKB[0], PKB[1], PKB[2], A); // TODO: Can return projective A?
  255. fpadd((digit_t *)&Montgomery_one, (digit_t *)&Montgomery_one, A24minus[0]);
  256. fp2add(A, A24minus, A24plus);
  257. fp2sub(A, A24minus, A24minus);
  258. // Retrieve kernel point
  259. LADDER3PT(PKB[0], PKB[1], PKB[2], (digit_t *)PrivateKeyB, BOB, R, A);
  260. // Traverse tree
  261. index = 0;
  262. for (row = 1; row < MAX_Bob; row++)
  263. {
  264. while (index < MAX_Bob - row)
  265. {
  266. fp2copy(R->X, pts[npts]->X);
  267. fp2copy(R->Z, pts[npts]->Z);
  268. pts_index[npts++] = index;
  269. m = strat_Bob[ii++];
  270. xTPLe(R, R, A24minus, A24plus, (int)m);
  271. index += m;
  272. }
  273. get_3_isog(R, A24minus, A24plus, coeff);
  274. for (i = 0; i < npts; i++)
  275. {
  276. eval_3_isog(pts[i], coeff);
  277. }
  278. fp2copy(pts[npts - 1]->X, R->X);
  279. fp2copy(pts[npts - 1]->Z, R->Z);
  280. index = pts_index[npts - 1];
  281. npts -= 1;
  282. }
  283. get_3_isog(R, A24minus, A24plus, coeff);
  284. fp2add(A24plus, A24minus, A);
  285. fp2add(A, A, A);
  286. fp2sub(A24plus, A24minus, A24plus);
  287. j_inv(A, A24plus, jinv);
  288. fp2_encode(jinv, SharedSecretB); // Format shared secret
  289. return 0;
  290. }