@pinkparrot/qsafe-mayo-wasm 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/.gitmodules +3 -0
  2. package/.vscode/launch.json +12 -0
  3. package/LICENSE +201 -0
  4. package/bridge/mayo1_bridge.c +26 -0
  5. package/bridge/mayo2_bridge.c +26 -0
  6. package/bridge/randombytes_inject.c +44 -0
  7. package/build_mayo1.ps1 +36 -0
  8. package/build_mayo2.ps1 +36 -0
  9. package/dist/mayo.browser.min.js +216 -0
  10. package/dist/mayo1.js +0 -0
  11. package/dist/mayo2.js +0 -0
  12. package/dist/mayo_api.js +139 -0
  13. package/dist/package.json +1 -0
  14. package/gitignore +2 -0
  15. package/index.mjs +1 -0
  16. package/mayo-c/.astylerc +16 -0
  17. package/mayo-c/.cmake/flags.cmake +45 -0
  18. package/mayo-c/.cmake/sanitizers.cmake +81 -0
  19. package/mayo-c/.cmake/target.cmake +71 -0
  20. package/mayo-c/.github/workflows/ci_clang.yml +61 -0
  21. package/mayo-c/.github/workflows/ci_gcc.yml +60 -0
  22. package/mayo-c/.github/workflows/cmake.yml +160 -0
  23. package/mayo-c/.github/workflows/macos_m1.yml +68 -0
  24. package/mayo-c/CMakeLists.txt +35 -0
  25. package/mayo-c/KAT/PQCsignKAT_24_MAYO_1.req +900 -0
  26. package/mayo-c/KAT/PQCsignKAT_24_MAYO_1.rsp +902 -0
  27. package/mayo-c/KAT/PQCsignKAT_24_MAYO_2.req +900 -0
  28. package/mayo-c/KAT/PQCsignKAT_24_MAYO_2.rsp +902 -0
  29. package/mayo-c/KAT/PQCsignKAT_32_MAYO_3.req +900 -0
  30. package/mayo-c/KAT/PQCsignKAT_32_MAYO_3.rsp +902 -0
  31. package/mayo-c/KAT/PQCsignKAT_40_MAYO_5.req +900 -0
  32. package/mayo-c/KAT/PQCsignKAT_40_MAYO_5.rsp +902 -0
  33. package/mayo-c/LICENSE +202 -0
  34. package/mayo-c/META/MAYO-1_META.yml +52 -0
  35. package/mayo-c/META/MAYO-2_META.yml +52 -0
  36. package/mayo-c/META/MAYO-3_META.yml +52 -0
  37. package/mayo-c/META/MAYO-5_META.yml +52 -0
  38. package/mayo-c/NOTICE +13 -0
  39. package/mayo-c/README.md +183 -0
  40. package/mayo-c/apps/CMakeLists.txt +31 -0
  41. package/mayo-c/apps/PQCgenKAT_sign.c +281 -0
  42. package/mayo-c/apps/example.c +151 -0
  43. package/mayo-c/apps/example_nistapi.c +124 -0
  44. package/mayo-c/include/mayo.h +442 -0
  45. package/mayo-c/include/mem.h +25 -0
  46. package/mayo-c/include/randombytes.h +31 -0
  47. package/mayo-c/scripts/contstants.py +141 -0
  48. package/mayo-c/scripts/find_irred_poly.sage +39 -0
  49. package/mayo-c/src/AVX2/arithmetic_common.h +159 -0
  50. package/mayo-c/src/AVX2/echelon_form.h +91 -0
  51. package/mayo-c/src/AVX2/echelon_form_loop.h +58 -0
  52. package/mayo-c/src/AVX2/shuffle_arithmetic.h +442 -0
  53. package/mayo-c/src/CMakeLists.txt +98 -0
  54. package/mayo-c/src/arithmetic.c +128 -0
  55. package/mayo-c/src/arithmetic.h +124 -0
  56. package/mayo-c/src/common/aes128ctr.c +293 -0
  57. package/mayo-c/src/common/aes_c.c +741 -0
  58. package/mayo-c/src/common/aes_ctr.h +32 -0
  59. package/mayo-c/src/common/aes_neon.c +201 -0
  60. package/mayo-c/src/common/debug_bench_tools.h +69 -0
  61. package/mayo-c/src/common/fips202.c +1093 -0
  62. package/mayo-c/src/common/fips202.h +12 -0
  63. package/mayo-c/src/common/mem.c +19 -0
  64. package/mayo-c/src/common/randombytes_ctrdrbg.c +141 -0
  65. package/mayo-c/src/common/randombytes_system.c +399 -0
  66. package/mayo-c/src/generic/arithmetic_dynamic.h +68 -0
  67. package/mayo-c/src/generic/arithmetic_fixed.h +84 -0
  68. package/mayo-c/src/generic/echelon_form.h +152 -0
  69. package/mayo-c/src/generic/ef_inner_loop.h +56 -0
  70. package/mayo-c/src/generic/generic_arithmetic.h +294 -0
  71. package/mayo-c/src/mayo.c +675 -0
  72. package/mayo-c/src/mayo_1/api.c +46 -0
  73. package/mayo-c/src/mayo_1/api.h +43 -0
  74. package/mayo-c/src/mayo_2/api.c +46 -0
  75. package/mayo-c/src/mayo_2/api.h +43 -0
  76. package/mayo-c/src/mayo_3/api.c +46 -0
  77. package/mayo-c/src/mayo_3/api.h +43 -0
  78. package/mayo-c/src/mayo_5/api.c +46 -0
  79. package/mayo-c/src/mayo_5/api.h +43 -0
  80. package/mayo-c/src/neon/arithmetic_common.h +132 -0
  81. package/mayo-c/src/neon/echelon_form.h +55 -0
  82. package/mayo-c/src/neon/echelon_form_loop.h +58 -0
  83. package/mayo-c/src/neon/shuffle_arithmetic.h +462 -0
  84. package/mayo-c/src/params.c +42 -0
  85. package/mayo-c/src/simple_arithmetic.h +138 -0
  86. package/mayo-c/test/CMakeLists.txt +51 -0
  87. package/mayo-c/test/bench.c +166 -0
  88. package/mayo-c/test/m1cycles.c +155 -0
  89. package/mayo-c/test/m1cycles.h +13 -0
  90. package/mayo-c/test/test_kat.c +271 -0
  91. package/mayo-c/test/test_mayo.c +139 -0
  92. package/mayo-c/test/test_sample_solution.c +75 -0
  93. package/mayo-c/test/test_various.c +680 -0
  94. package/package.json +39 -0
  95. package/publish.bat +22 -0
  96. package/readme.md +80 -0
  97. package/test/test.mjs +42 -0
@@ -0,0 +1,159 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+
3
+ #ifndef ARITHMETIC_COMMON_H
4
+ #define ARITHMETIC_COMMON_H
5
+
6
+ #include <stdint.h>
7
+ #include <immintrin.h>
8
+ #include <mem.h>
9
+
10
+ #define K_OVER_2 ((K_MAX+1)/2)
11
+
12
+ static const unsigned char __gf16_mulbase[128] __attribute__((aligned(32))) = {
13
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
14
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x03, 0x01, 0x07, 0x05, 0x0b, 0x09, 0x0f, 0x0d, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x03, 0x01, 0x07, 0x05, 0x0b, 0x09, 0x0f, 0x0d,
15
+ 0x00, 0x04, 0x08, 0x0c, 0x03, 0x07, 0x0b, 0x0f, 0x06, 0x02, 0x0e, 0x0a, 0x05, 0x01, 0x0d, 0x09, 0x00, 0x04, 0x08, 0x0c, 0x03, 0x07, 0x0b, 0x0f, 0x06, 0x02, 0x0e, 0x0a, 0x05, 0x01, 0x0d, 0x09,
16
+ 0x00, 0x08, 0x03, 0x0b, 0x06, 0x0e, 0x05, 0x0d, 0x0c, 0x04, 0x0f, 0x07, 0x0a, 0x02, 0x09, 0x01, 0x00, 0x08, 0x03, 0x0b, 0x06, 0x0e, 0x05, 0x0d, 0x0c, 0x04, 0x0f, 0x07, 0x0a, 0x02, 0x09, 0x01
17
+ };
18
+
19
+ //
20
+ // generate multiplication table for '4-bit' variable 'b'. Taken from OV paper!
21
+ //
22
+ static inline __m256i tbl32_gf16_multab2( uint8_t b ) {
23
+
24
+ __m256i bx = _mm256_set1_epi16( b & 0xf );
25
+ __m256i b1 = _mm256_srli_epi16( bx, 1 );
26
+
27
+ const __m256i tab0 = _mm256_load_si256((__m256i const *) (__gf16_mulbase + 32 * 0));
28
+ const __m256i tab1 = _mm256_load_si256((__m256i const *) (__gf16_mulbase + 32 * 1));
29
+ const __m256i tab2 = _mm256_load_si256((__m256i const *) (__gf16_mulbase + 32 * 2));
30
+ const __m256i tab3 = _mm256_load_si256((__m256i const *) (__gf16_mulbase + 32 * 3));
31
+
32
+ __m256i mask_1 = _mm256_set1_epi16(1);
33
+ __m256i mask_4 = _mm256_set1_epi16(4);
34
+ __m256i mask_0 = _mm256_setzero_si256();
35
+
36
+ return ( tab0 & _mm256_cmpgt_epi16( bx & mask_1, mask_0) )
37
+ ^ ( tab1 & _mm256_cmpgt_epi16( b1 & mask_1, mask_0) )
38
+ ^ ( tab2 & _mm256_cmpgt_epi16( bx & mask_4, mask_0) )
39
+ ^ ( tab3 & _mm256_cmpgt_epi16( b1 & mask_4, mask_0) );
40
+ }
41
+
42
+ static inline __m256i linear_transform_8x8_256b( __m256i tab_l, __m256i tab_h, __m256i v, __m256i mask_f ) {
43
+ return _mm256_shuffle_epi8(tab_l, v & mask_f)^_mm256_shuffle_epi8(tab_h, _mm256_srli_epi16(v, 4)&mask_f);
44
+ }
45
+
46
+ static inline __m256i gf16v_mul( __m256i a, uint8_t b ) {
47
+ __m256i multab_l = tbl32_gf16_multab2( b );
48
+ __m256i multab_h = _mm256_slli_epi16( multab_l, 4 );
49
+
50
+ return linear_transform_8x8_256b( multab_l, multab_h, a, _mm256_set1_epi8(0xf) );
51
+ }
52
+
53
+ #define O_AVX_ROUND_UP_ ((O_MAX + 1)/2*2)
54
+
55
+ static
56
+ inline void mayo_O_multabs(const unsigned char *O, __m256i *O_multabs){
57
+ // build multiplication tables
58
+ for (size_t r = 0; r < V_MAX; r++)
59
+ {
60
+ size_t c = 0;
61
+ for (; c + 1 < O_MAX; c+=2)
62
+ {
63
+ O_multabs[O_AVX_ROUND_UP_/2*r + c/2] = tbl32_gf16_multab2(O[O_MAX*r + c]) ^ _mm256_slli_epi16(tbl32_gf16_multab2(O[O_MAX*r + c + 1]), 4);
64
+ }
65
+ #if O_MAX % 2 == 1
66
+ {
67
+ O_multabs[O_AVX_ROUND_UP_/2*r + c/2] = tbl32_gf16_multab2(O[O_MAX*r + c]);
68
+ }
69
+ #endif
70
+ }
71
+ }
72
+
73
+
74
+ static
75
+ inline void mayo_V_multabs(const unsigned char *V, __m256i *V_multabs){
76
+ // build multiplication tables
77
+ size_t r;
78
+ for (size_t c = 0; c < V_MAX; c++)
79
+ {
80
+ for (r = 0; r+1 < K_MAX; r+= 2)
81
+ {
82
+ V_multabs[K_OVER_2*c + r/2] = tbl32_gf16_multab2(V[V_MAX*r + c]) ^ _mm256_slli_epi16(tbl32_gf16_multab2(V[V_MAX*(r+1) + c]), 4);
83
+ }
84
+ #if K_MAX % 2 == 1
85
+ V_multabs[K_OVER_2*c + r/2] = tbl32_gf16_multab2(V[V_MAX*r + c]);
86
+ #endif
87
+ }
88
+ }
89
+
90
+ static const unsigned char mayo_gf16_mul[512] __attribute__((aligned(32))) = {
91
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
92
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
93
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
94
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
95
+ 0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e, 0x03,0x01,0x07,0x05,0x0b,0x09,0x0f,0x0d,
96
+ 0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e, 0x03,0x01,0x07,0x05,0x0b,0x09,0x0f,0x0d,
97
+ 0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09, 0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,
98
+ 0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09, 0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,
99
+ 0x00,0x04,0x08,0x0c,0x03,0x07,0x0b,0x0f, 0x06,0x02,0x0e,0x0a,0x05,0x01,0x0d,0x09,
100
+ 0x00,0x04,0x08,0x0c,0x03,0x07,0x0b,0x0f, 0x06,0x02,0x0e,0x0a,0x05,0x01,0x0d,0x09,
101
+ 0x00,0x05,0x0a,0x0f,0x07,0x02,0x0d,0x08, 0x0e,0x0b,0x04,0x01,0x09,0x0c,0x03,0x06,
102
+ 0x00,0x05,0x0a,0x0f,0x07,0x02,0x0d,0x08, 0x0e,0x0b,0x04,0x01,0x09,0x0c,0x03,0x06,
103
+ 0x00,0x06,0x0c,0x0a,0x0b,0x0d,0x07,0x01, 0x05,0x03,0x09,0x0f,0x0e,0x08,0x02,0x04,
104
+ 0x00,0x06,0x0c,0x0a,0x0b,0x0d,0x07,0x01, 0x05,0x03,0x09,0x0f,0x0e,0x08,0x02,0x04,
105
+ 0x00,0x07,0x0e,0x09,0x0f,0x08,0x01,0x06, 0x0d,0x0a,0x03,0x04,0x02,0x05,0x0c,0x0b,
106
+ 0x00,0x07,0x0e,0x09,0x0f,0x08,0x01,0x06, 0x0d,0x0a,0x03,0x04,0x02,0x05,0x0c,0x0b,
107
+ 0x00,0x08,0x03,0x0b,0x06,0x0e,0x05,0x0d, 0x0c,0x04,0x0f,0x07,0x0a,0x02,0x09,0x01,
108
+ 0x00,0x08,0x03,0x0b,0x06,0x0e,0x05,0x0d, 0x0c,0x04,0x0f,0x07,0x0a,0x02,0x09,0x01,
109
+ 0x00,0x09,0x01,0x08,0x02,0x0b,0x03,0x0a, 0x04,0x0d,0x05,0x0c,0x06,0x0f,0x07,0x0e,
110
+ 0x00,0x09,0x01,0x08,0x02,0x0b,0x03,0x0a, 0x04,0x0d,0x05,0x0c,0x06,0x0f,0x07,0x0e,
111
+ 0x00,0x0a,0x07,0x0d,0x0e,0x04,0x09,0x03, 0x0f,0x05,0x08,0x02,0x01,0x0b,0x06,0x0c,
112
+ 0x00,0x0a,0x07,0x0d,0x0e,0x04,0x09,0x03, 0x0f,0x05,0x08,0x02,0x01,0x0b,0x06,0x0c,
113
+ 0x00,0x0b,0x05,0x0e,0x0a,0x01,0x0f,0x04, 0x07,0x0c,0x02,0x09,0x0d,0x06,0x08,0x03,
114
+ 0x00,0x0b,0x05,0x0e,0x0a,0x01,0x0f,0x04, 0x07,0x0c,0x02,0x09,0x0d,0x06,0x08,0x03,
115
+ 0x00,0x0c,0x0b,0x07,0x05,0x09,0x0e,0x02, 0x0a,0x06,0x01,0x0d,0x0f,0x03,0x04,0x08,
116
+ 0x00,0x0c,0x0b,0x07,0x05,0x09,0x0e,0x02, 0x0a,0x06,0x01,0x0d,0x0f,0x03,0x04,0x08,
117
+ 0x00,0x0d,0x09,0x04,0x01,0x0c,0x08,0x05, 0x02,0x0f,0x0b,0x06,0x03,0x0e,0x0a,0x07,
118
+ 0x00,0x0d,0x09,0x04,0x01,0x0c,0x08,0x05, 0x02,0x0f,0x0b,0x06,0x03,0x0e,0x0a,0x07,
119
+ 0x00,0x0e,0x0f,0x01,0x0d,0x03,0x02,0x0c, 0x09,0x07,0x06,0x08,0x04,0x0a,0x0b,0x05,
120
+ 0x00,0x0e,0x0f,0x01,0x0d,0x03,0x02,0x0c, 0x09,0x07,0x06,0x08,0x04,0x0a,0x0b,0x05,
121
+ 0x00,0x0f,0x0d,0x02,0x09,0x06,0x04,0x0b, 0x01,0x0e,0x0c,0x03,0x08,0x07,0x05,0x0a,
122
+ 0x00,0x0f,0x0d,0x02,0x09,0x06,0x04,0x0b, 0x01,0x0e,0x0c,0x03,0x08,0x07,0x05,0x0a};
123
+
124
+
125
+ static
126
+ inline void mayo_S1_multabs(const unsigned char *S1, __m256i *S1_multabs) {
127
+ size_t r;
128
+ for (size_t c = 0; c < V_MAX; c++)
129
+ {
130
+ for (r = 0; r+1 < K_MAX; r+= 2)
131
+ {
132
+ S1_multabs[K_OVER_2*c + r/2] = _mm256_load_si256((__m256i *)(mayo_gf16_mul + 32*S1[V_MAX*r + c]))
133
+ ^ _mm256_slli_epi16(_mm256_load_si256((__m256i *)(mayo_gf16_mul + 32*S1[V_MAX*(r+1) + c])), 4);
134
+ }
135
+ #if K_MAX % 2 == 1
136
+ S1_multabs[K_OVER_2*c + r/2] = _mm256_load_si256((__m256i *)(mayo_gf16_mul + 32*S1[V_MAX*r + c]));
137
+ #endif
138
+ }
139
+ }
140
+
141
+ static
142
+ inline void mayo_S2_multabs(const unsigned char *S2, __m256i *S2_multabs) {
143
+ // build multiplication tables
144
+ size_t r;
145
+ for (size_t c = 0; c < O_MAX; c++)
146
+ {
147
+ for (r = 0; r+1 < K_MAX; r+= 2)
148
+ {
149
+ S2_multabs[K_OVER_2*c + r/2] = _mm256_load_si256((__m256i *)(mayo_gf16_mul + 32*S2[O_MAX*r + c]))
150
+ ^ _mm256_slli_epi16(_mm256_load_si256((__m256i *)(mayo_gf16_mul + 32*S2[O_MAX*(r+1) + c])), 4);
151
+ }
152
+ #if K_MAX % 2 == 1
153
+ S2_multabs[K_OVER_2*c + r/2] = _mm256_load_si256((__m256i *)(mayo_gf16_mul + 32*S2[O_MAX*r + c])) ;
154
+ #endif
155
+ }
156
+ }
157
+
158
+ #endif
159
+
@@ -0,0 +1,91 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+
3
+ #include <immintrin.h>
4
+ #include <stdint.h>
5
+
6
+
7
+ #define MAYO_MAX(x, y) (((x) > (y)) ? (x) : (y))
8
+ #define MAYO_MIN(x, y) (((x) < (y)) ? (x) : (y))
9
+
10
+
11
+ //
12
+ // generate multiplication table for '4-bit' variable 'b'. From https://eprint.iacr.org/2023/059/.
13
+ //
14
+ static inline __m256i tbl32_gf16_multab( uint8_t b ) {
15
+ __m256i bx = _mm256_set1_epi16( b & 0xf );
16
+ __m256i b1 = _mm256_srli_epi16( bx, 1 );
17
+
18
+ const __m256i tab0 = _mm256_load_si256((__m256i const *) (__gf16_mulbase + 32 * 0));
19
+ const __m256i tab1 = _mm256_load_si256((__m256i const *) (__gf16_mulbase + 32 * 1));
20
+ const __m256i tab2 = _mm256_load_si256((__m256i const *) (__gf16_mulbase + 32 * 2));
21
+ const __m256i tab3 = _mm256_load_si256((__m256i const *) (__gf16_mulbase + 32 * 3));
22
+
23
+ __m256i mask_1 = _mm256_set1_epi16(1);
24
+ __m256i mask_4 = _mm256_set1_epi16(4);
25
+ __m256i mask_0 = _mm256_setzero_si256();
26
+
27
+ return ( tab0 & _mm256_cmpgt_epi16( bx & mask_1, mask_0) )
28
+ ^ ( tab1 & _mm256_cmpgt_epi16( b1 & mask_1, mask_0) )
29
+ ^ ( tab2 & _mm256_cmpgt_epi16( bx & mask_4, mask_0) )
30
+ ^ ( tab3 & _mm256_cmpgt_epi16( b1 & mask_4, mask_0) );
31
+ }
32
+
33
+ /* put matrix in row echelon form with ones on first nonzero entries in constant time*/
34
+ static inline void EF(unsigned char *A, int _nrows, int _ncols) {
35
+
36
+ (void) _nrows;
37
+ (void) _ncols;
38
+
39
+ #define nrows M_MAX
40
+ #define ncols (K_MAX * O_MAX + 1)
41
+
42
+ #define AVX_REGS_PER_ROW ((K_MAX * O_MAX + 1 + 31) / 32)
43
+ #define MAX_COLS (AVX_REGS_PER_ROW * 32)
44
+
45
+ __m256i _pivot_row[AVX_REGS_PER_ROW];
46
+ __m256i A_avx[AVX_REGS_PER_ROW* M_MAX];
47
+
48
+ unsigned char* pivot_row_bytes = (unsigned char*) _pivot_row;
49
+ unsigned char* A_bytes = (unsigned char*) A_avx;
50
+
51
+ // load A in the tail of AVX2 registers
52
+ for (int i = 0; i < nrows; i++) {
53
+ for (int j = 0; j < ncols; j++)
54
+ {
55
+ A_bytes[i*MAX_COLS + (MAX_COLS - ncols) + j] = A[ i*ncols + j ];
56
+ }
57
+ }
58
+
59
+ // pivot row is secret, pivot col is not
60
+ unsigned char inverse;
61
+ int pivot_row = 0;
62
+ int pivot_col = MAYO_MAX(MAX_COLS - ncols,0);
63
+ for (; pivot_col < MAX_COLS-160; pivot_col++) {
64
+ #include "echelon_form_loop.h"
65
+ }
66
+ for (; pivot_col < MAX_COLS-128; pivot_col++) {
67
+ #include "echelon_form_loop.h"
68
+ }
69
+ for (; pivot_col < MAX_COLS-96; pivot_col++) {
70
+ #include "echelon_form_loop.h"
71
+ }
72
+ for (; pivot_col < MAX_COLS-64; pivot_col++) {
73
+ #include "echelon_form_loop.h"
74
+ }
75
+ for (; pivot_col < MAX_COLS-32; pivot_col++) {
76
+ #include "echelon_form_loop.h"
77
+ }
78
+ for (; pivot_col < MAX_COLS; pivot_col++) {
79
+ #include "echelon_form_loop.h"
80
+ }
81
+
82
+ // write the matrix A back
83
+ for (int i = 0; i < nrows; i++) {
84
+ for (int j = 0; j < ncols; j++) {
85
+ A[i * ncols + j] = A_bytes[i*AVX_REGS_PER_ROW*32 + (MAX_COLS - ncols) + j];
86
+ }
87
+ }
88
+ mayo_secure_clear(_pivot_row, AVX_REGS_PER_ROW * 32);
89
+ mayo_secure_clear(A_avx, AVX_REGS_PER_ROW * 32 * nrows);
90
+ }
91
+
@@ -0,0 +1,58 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+
3
+ int pivot_col_rounded = pivot_col/32;
4
+
5
+ int pivot_row_lower_bound = MAYO_MAX(0, pivot_col + nrows - MAX_COLS);
6
+ int pivot_row_upper_bound = MAYO_MIN(nrows - 1, pivot_col - MAX_COLS + ncols);
7
+ /* the pivot row is guaranteed to be between these lower and upper bounds if A has full rank*/
8
+
9
+ /* zero out pivot row */
10
+ for (int i = pivot_col_rounded; i < AVX_REGS_PER_ROW; i++) {
11
+ _pivot_row[i] = _mm256_set1_epi8(0);
12
+ }
13
+
14
+ /* try to get a pivot row in constant time */
15
+ unsigned char pivot = 0;
16
+ uint32_t pivot_is_zero = -1;
17
+ for (int row = pivot_row_lower_bound;
18
+ row <= MAYO_MIN(nrows - 1, pivot_row_upper_bound + 32); row++) {
19
+ uint32_t is_pivot_row = ~ct_compare_32(row, pivot_row);
20
+ uint32_t below_pivot_row = ct_is_greater_than(row, pivot_row);
21
+ __m256i mask = _mm256_set1_epi32( is_pivot_row | (below_pivot_row & pivot_is_zero) );
22
+ for (int j = pivot_col_rounded; j < AVX_REGS_PER_ROW; j++) {
23
+ _pivot_row[j] ^= mask & A_avx[row * AVX_REGS_PER_ROW + j];
24
+ }
25
+ pivot = pivot_row_bytes[pivot_col];
26
+ pivot_is_zero = ~ct_compare_32((int) pivot, 0);
27
+ }
28
+
29
+ /* multiply pivot row by inverse of pivot */
30
+ inverse = inverse_f(pivot);
31
+ __m256i inverse_multab = tbl32_gf16_multab(inverse);
32
+
33
+ for (int j = pivot_col_rounded; j < AVX_REGS_PER_ROW; j++) {
34
+ _pivot_row[j] = _mm256_shuffle_epi8(inverse_multab, _pivot_row[j]);
35
+ }
36
+
37
+ /* conditionally write pivot row to the correct row, if there is a nonzero pivot */
38
+ /* eliminate entries below pivot */
39
+ for (int row = pivot_row_lower_bound; row < nrows; row++) {
40
+ unsigned char below_pivot = (unsigned char) (ct_is_greater_than(row, pivot_row));
41
+ unsigned char elt_to_elim = A_bytes[row*AVX_REGS_PER_ROW*32 + pivot_col];
42
+
43
+ __m256i multab = tbl32_gf16_multab(below_pivot & elt_to_elim);
44
+ if (row <= pivot_row_upper_bound) {
45
+ __m256i mask = _mm256_set1_epi32(~ct_compare_32(row, pivot_row) & ~pivot_is_zero);
46
+ for (int col = pivot_col_rounded; col < AVX_REGS_PER_ROW; col++) {
47
+ A_avx[row*AVX_REGS_PER_ROW + col] = _mm256_blendv_epi8(A_avx[row*AVX_REGS_PER_ROW + col], _pivot_row[col], mask) ^
48
+ _mm256_shuffle_epi8(multab, _pivot_row[col]);
49
+ }
50
+ } else {
51
+ for (int j = pivot_col_rounded; j < AVX_REGS_PER_ROW; j++) {
52
+ A_avx[row*AVX_REGS_PER_ROW + j] ^= _mm256_shuffle_epi8(multab, _pivot_row[j]);
53
+ }
54
+ }
55
+ }
56
+
57
+ pivot_row += (-(int32_t)(~pivot_is_zero));
58
+