Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

206 řádky
4.5 KiB

  1. /*
  2. this file is for functions for field arithmetic
  3. */
  4. #include "gf.h"
  5. #include "params.h"
  6. /* check if a == 0 */
  7. gf PQCLEAN_MCELIECE460896F_AVX_gf_iszero(gf a) {
  8. uint32_t t = a;
  9. t -= 1;
  10. t >>= 19;
  11. return (gf) t;
  12. }
  13. /* field multiplication */
  14. gf PQCLEAN_MCELIECE460896F_AVX_gf_mul(gf in0, gf in1) {
  15. int i;
  16. uint64_t tmp;
  17. uint64_t t0;
  18. uint64_t t1;
  19. uint64_t t;
  20. t0 = in0;
  21. t1 = in1;
  22. tmp = t0 * (t1 & 1);
  23. for (i = 1; i < GFBITS; i++) {
  24. tmp ^= (t0 * (t1 & ((uint64_t)1 << i)));
  25. }
  26. //
  27. t = tmp & 0x1FF0000;
  28. tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13);
  29. t = tmp & 0x000E000;
  30. tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13);
  31. return tmp & GFMASK;
  32. }
  33. /* square twice */
  34. static inline gf gf_sq2(gf in) {
  35. int i;
  36. const uint64_t B[] = {0x1111111111111111,
  37. 0x0303030303030303,
  38. 0x000F000F000F000F,
  39. 0x000000FF000000FF
  40. };
  41. const uint64_t M[] = {0x0001FF0000000000,
  42. 0x000000FF80000000,
  43. 0x000000007FC00000,
  44. 0x00000000003FE000
  45. };
  46. uint64_t x = in;
  47. uint64_t t;
  48. x = (x | (x << 24)) & B[3];
  49. x = (x | (x << 12)) & B[2];
  50. x = (x | (x << 6)) & B[1];
  51. x = (x | (x << 3)) & B[0];
  52. for (i = 0; i < 4; i++) {
  53. t = x & M[i];
  54. x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13);
  55. }
  56. return x & GFMASK;
  57. }
  58. /* square and multiply */
  59. static inline gf gf_sqmul(gf in, gf m) {
  60. int i;
  61. uint64_t x;
  62. uint64_t t0;
  63. uint64_t t1;
  64. uint64_t t;
  65. const uint64_t M[] = {0x0000001FF0000000,
  66. 0x000000000FF80000,
  67. 0x000000000007E000
  68. };
  69. t0 = in;
  70. t1 = m;
  71. x = (t1 << 6) * (t0 & (1 << 6));
  72. t0 ^= (t0 << 7);
  73. x ^= (t1 * (t0 & (0x04001)));
  74. x ^= (t1 * (t0 & (0x08002))) << 1;
  75. x ^= (t1 * (t0 & (0x10004))) << 2;
  76. x ^= (t1 * (t0 & (0x20008))) << 3;
  77. x ^= (t1 * (t0 & (0x40010))) << 4;
  78. x ^= (t1 * (t0 & (0x80020))) << 5;
  79. for (i = 0; i < 3; i++) {
  80. t = x & M[i];
  81. x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13);
  82. }
  83. return x & GFMASK;
  84. }
  85. /* square twice and multiply */
  86. static inline gf gf_sq2mul(gf in, gf m) {
  87. int i;
  88. uint64_t x;
  89. uint64_t t0;
  90. uint64_t t1;
  91. uint64_t t;
  92. const uint64_t M[] = {0x1FF0000000000000,
  93. 0x000FF80000000000,
  94. 0x000007FC00000000,
  95. 0x00000003FE000000,
  96. 0x0000000001FE0000,
  97. 0x000000000001E000
  98. };
  99. t0 = in;
  100. t1 = m;
  101. x = (t1 << 18) * (t0 & (1 << 6));
  102. t0 ^= (t0 << 21);
  103. x ^= (t1 * (t0 & (0x010000001)));
  104. x ^= (t1 * (t0 & (0x020000002))) << 3;
  105. x ^= (t1 * (t0 & (0x040000004))) << 6;
  106. x ^= (t1 * (t0 & (0x080000008))) << 9;
  107. x ^= (t1 * (t0 & (0x100000010))) << 12;
  108. x ^= (t1 * (t0 & (0x200000020))) << 15;
  109. for (i = 0; i < 6; i++) {
  110. t = x & M[i];
  111. x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13);
  112. }
  113. return x & GFMASK;
  114. }
  115. /* return num/den */
  116. gf PQCLEAN_MCELIECE460896F_AVX_gf_frac(gf den, gf num) {
  117. gf tmp_11;
  118. gf tmp_1111;
  119. gf out;
  120. tmp_11 = gf_sqmul(den, den); // ^11
  121. tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111
  122. out = gf_sq2(tmp_1111);
  123. out = gf_sq2mul(out, tmp_1111); // ^11111111
  124. out = gf_sq2(out);
  125. out = gf_sq2mul(out, tmp_1111); // ^111111111111
  126. return gf_sqmul(out, num); // ^1111111111110 = ^-1
  127. }
  128. /* return 1/den */
  129. gf PQCLEAN_MCELIECE460896F_AVX_gf_inv(gf in) {
  130. return PQCLEAN_MCELIECE460896F_AVX_gf_frac(in, ((gf) 1));
  131. }
  132. /* multiplication in GF((2^m)^t) */
  133. void PQCLEAN_MCELIECE460896F_AVX_GF_mul(gf *out, const gf *in0, const gf *in1) {
  134. int i, j;
  135. gf prod[191];
  136. for (i = 0; i < 191; i++) {
  137. prod[i] = 0;
  138. }
  139. for (i = 0; i < 96; i++) {
  140. for (j = 0; j < 96; j++) {
  141. prod[i + j] ^= PQCLEAN_MCELIECE460896F_AVX_gf_mul(in0[i], in1[j]);
  142. }
  143. }
  144. //
  145. for (i = 190; i >= 96; i--) {
  146. prod[i - 85] ^= PQCLEAN_MCELIECE460896F_AVX_gf_mul(prod[i], (gf) 714);
  147. prod[i - 91] ^= PQCLEAN_MCELIECE460896F_AVX_gf_mul(prod[i], (gf) 5296);
  148. prod[i - 92] ^= PQCLEAN_MCELIECE460896F_AVX_gf_mul(prod[i], (gf) 728);
  149. prod[i - 96] ^= PQCLEAN_MCELIECE460896F_AVX_gf_mul(prod[i], (gf) 5881);
  150. }
  151. for (i = 0; i < 96; i++) {
  152. out[i] = prod[i];
  153. }
  154. }