kpqc 0.1.0

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 (191) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +21 -0
  4. data/README.md +174 -0
  5. data/Rakefile +57 -0
  6. data/THIRD_PARTY_NOTICES.md +53 -0
  7. data/ext/kpqc/aimer128f/extconf.rb +4 -0
  8. data/ext/kpqc/aimer128s/extconf.rb +4 -0
  9. data/ext/kpqc/aimer192f/extconf.rb +4 -0
  10. data/ext/kpqc/aimer192s/extconf.rb +4 -0
  11. data/ext/kpqc/aimer256f/extconf.rb +4 -0
  12. data/ext/kpqc/aimer256s/extconf.rb +4 -0
  13. data/ext/kpqc/extconf_helper.rb +93 -0
  14. data/ext/kpqc/haetae2/extconf.rb +4 -0
  15. data/ext/kpqc/haetae3/extconf.rb +4 -0
  16. data/ext/kpqc/haetae5/extconf.rb +4 -0
  17. data/ext/kpqc/module.c +195 -0
  18. data/ext/kpqc/ntruplus1152/extconf.rb +4 -0
  19. data/ext/kpqc/ntruplus768/extconf.rb +4 -0
  20. data/ext/kpqc/ntruplus864/extconf.rb +4 -0
  21. data/ext/kpqc/randombytes.c +107 -0
  22. data/ext/kpqc/smaugt128/extconf.rb +4 -0
  23. data/ext/kpqc/smaugt192/extconf.rb +4 -0
  24. data/ext/kpqc/smaugt256/extconf.rb +4 -0
  25. data/ext/kpqc/timer/extconf.rb +4 -0
  26. data/kpqc.gemspec +41 -0
  27. data/lib/kpqc/aimer.rb +38 -0
  28. data/lib/kpqc/api.rb +129 -0
  29. data/lib/kpqc/haetae.rb +25 -0
  30. data/lib/kpqc/ntruplus.rb +25 -0
  31. data/lib/kpqc/smaugt.rb +29 -0
  32. data/lib/kpqc/types.rb +103 -0
  33. data/lib/kpqc/version.rb +6 -0
  34. data/lib/kpqc.rb +33 -0
  35. data/test/algorithm_test.rb +111 -0
  36. data/test/api_test.rb +52 -0
  37. data/test/interop.mjs +34 -0
  38. data/test/interop_test.rb +82 -0
  39. data/test/kat/aimer128f.rsp +10 -0
  40. data/test/kat/aimer128s.rsp +10 -0
  41. data/test/kat/aimer192f.rsp +10 -0
  42. data/test/kat/aimer192s.rsp +10 -0
  43. data/test/kat/aimer256f.rsp +10 -0
  44. data/test/kat/aimer256s.rsp +10 -0
  45. data/test/kat/haetae2.rsp +10 -0
  46. data/test/kat/haetae3.rsp +10 -0
  47. data/test/kat/haetae5.rsp +10 -0
  48. data/test/kat/ntruplus1152.rsp +8 -0
  49. data/test/kat/ntruplus768.rsp +8 -0
  50. data/test/kat/ntruplus864.rsp +8 -0
  51. data/test/kat/smaugt128.rsp +8 -0
  52. data/test/kat/smaugt192.rsp +8 -0
  53. data/test/kat/smaugt256.rsp +8 -0
  54. data/test/kat/timer.rsp +8 -0
  55. data/test/kat_drbg.rb +155 -0
  56. data/test/kat_test.rb +99 -0
  57. data/test/test_helper.rb +21 -0
  58. data/vendor/AIMer/LICENSE +21 -0
  59. data/vendor/AIMer/aim2.c +163 -0
  60. data/vendor/AIMer/aim2.h +36 -0
  61. data/vendor/AIMer/aim2_constant.h +74 -0
  62. data/vendor/AIMer/api.h +42 -0
  63. data/vendor/AIMer/common/crypto_declassify.h +7 -0
  64. data/vendor/AIMer/common/fips202.c +878 -0
  65. data/vendor/AIMer/common/fips202.h +166 -0
  66. data/vendor/AIMer/common/rng.h +56 -0
  67. data/vendor/AIMer/field.h +43 -0
  68. data/vendor/AIMer/field128.c +454 -0
  69. data/vendor/AIMer/field192.c +485 -0
  70. data/vendor/AIMer/field256.c +564 -0
  71. data/vendor/AIMer/hash.c +50 -0
  72. data/vendor/AIMer/hash.h +37 -0
  73. data/vendor/AIMer/params/params-aimer-128f.h +34 -0
  74. data/vendor/AIMer/params/params-aimer-128s.h +34 -0
  75. data/vendor/AIMer/params/params-aimer-192f.h +34 -0
  76. data/vendor/AIMer/params/params-aimer-192s.h +34 -0
  77. data/vendor/AIMer/params/params-aimer-256f.h +34 -0
  78. data/vendor/AIMer/params/params-aimer-256s.h +34 -0
  79. data/vendor/AIMer/params.h +5 -0
  80. data/vendor/AIMer/sign.c +631 -0
  81. data/vendor/AIMer/sign.h +40 -0
  82. data/vendor/AIMer/tree.c +75 -0
  83. data/vendor/AIMer/tree.h +26 -0
  84. data/vendor/HAETAE/LICENSE +22 -0
  85. data/vendor/HAETAE/include/api.h +54 -0
  86. data/vendor/HAETAE/include/common.h +12 -0
  87. data/vendor/HAETAE/include/config.h +42 -0
  88. data/vendor/HAETAE/include/decompose.h +19 -0
  89. data/vendor/HAETAE/include/encoding.h +20 -0
  90. data/vendor/HAETAE/include/fft.h +26 -0
  91. data/vendor/HAETAE/include/fips202.h +40 -0
  92. data/vendor/HAETAE/include/fixpoint.h +125 -0
  93. data/vendor/HAETAE/include/ntt.h +16 -0
  94. data/vendor/HAETAE/include/packing.h +58 -0
  95. data/vendor/HAETAE/include/params.h +117 -0
  96. data/vendor/HAETAE/include/poly.h +65 -0
  97. data/vendor/HAETAE/include/polyfix.h +65 -0
  98. data/vendor/HAETAE/include/polymat.h +32 -0
  99. data/vendor/HAETAE/include/polyvec.h +131 -0
  100. data/vendor/HAETAE/include/randombytes.h +39 -0
  101. data/vendor/HAETAE/include/rans_byte.h +335 -0
  102. data/vendor/HAETAE/include/reduce.h +31 -0
  103. data/vendor/HAETAE/include/sampler.h +23 -0
  104. data/vendor/HAETAE/include/symmetric.h +52 -0
  105. data/vendor/HAETAE/src/decompose.c +73 -0
  106. data/vendor/HAETAE/src/encoding.c +700 -0
  107. data/vendor/HAETAE/src/fft.c +235 -0
  108. data/vendor/HAETAE/src/fips202.c +745 -0
  109. data/vendor/HAETAE/src/fixpoint.c +143 -0
  110. data/vendor/HAETAE/src/ntt.c +98 -0
  111. data/vendor/HAETAE/src/packing.c +595 -0
  112. data/vendor/HAETAE/src/poly.c +371 -0
  113. data/vendor/HAETAE/src/polyfix.c +298 -0
  114. data/vendor/HAETAE/src/polymat.c +82 -0
  115. data/vendor/HAETAE/src/polyvec.c +534 -0
  116. data/vendor/HAETAE/src/reduce.c +96 -0
  117. data/vendor/HAETAE/src/sampler.c +310 -0
  118. data/vendor/HAETAE/src/sign.c +558 -0
  119. data/vendor/HAETAE/src/symmetric-shake.c +50 -0
  120. data/vendor/NTRUplus/LICENSE +21 -0
  121. data/vendor/NTRUplus/NTRU+1152/api.h +24 -0
  122. data/vendor/NTRUplus/NTRU+1152/fips202/fips202.c +878 -0
  123. data/vendor/NTRUplus/NTRU+1152/fips202/fips202.h +166 -0
  124. data/vendor/NTRUplus/NTRU+1152/kem.c +286 -0
  125. data/vendor/NTRUplus/NTRU+1152/ntt.c +394 -0
  126. data/vendor/NTRUplus/NTRU+1152/ntt.h +16 -0
  127. data/vendor/NTRUplus/NTRU+1152/params.h +18 -0
  128. data/vendor/NTRUplus/NTRU+1152/poly.c +318 -0
  129. data/vendor/NTRUplus/NTRU+1152/poly.h +31 -0
  130. data/vendor/NTRUplus/NTRU+1152/randombytes.h +9 -0
  131. data/vendor/NTRUplus/NTRU+1152/symmetric.c +39 -0
  132. data/vendor/NTRUplus/NTRU+1152/symmetric.h +12 -0
  133. data/vendor/NTRUplus/NTRU+768/api.h +24 -0
  134. data/vendor/NTRUplus/NTRU+768/fips202/fips202.c +878 -0
  135. data/vendor/NTRUplus/NTRU+768/fips202/fips202.h +166 -0
  136. data/vendor/NTRUplus/NTRU+768/kem.c +286 -0
  137. data/vendor/NTRUplus/NTRU+768/ntt.c +379 -0
  138. data/vendor/NTRUplus/NTRU+768/ntt.h +16 -0
  139. data/vendor/NTRUplus/NTRU+768/params.h +18 -0
  140. data/vendor/NTRUplus/NTRU+768/poly.c +320 -0
  141. data/vendor/NTRUplus/NTRU+768/poly.h +31 -0
  142. data/vendor/NTRUplus/NTRU+768/randombytes.h +9 -0
  143. data/vendor/NTRUplus/NTRU+768/symmetric.c +39 -0
  144. data/vendor/NTRUplus/NTRU+768/symmetric.h +12 -0
  145. data/vendor/NTRUplus/NTRU+864/api.h +24 -0
  146. data/vendor/NTRUplus/NTRU+864/fips202/fips202.c +878 -0
  147. data/vendor/NTRUplus/NTRU+864/fips202/fips202.h +166 -0
  148. data/vendor/NTRUplus/NTRU+864/kem.c +286 -0
  149. data/vendor/NTRUplus/NTRU+864/ntt.c +383 -0
  150. data/vendor/NTRUplus/NTRU+864/ntt.h +16 -0
  151. data/vendor/NTRUplus/NTRU+864/params.h +18 -0
  152. data/vendor/NTRUplus/NTRU+864/poly.c +314 -0
  153. data/vendor/NTRUplus/NTRU+864/poly.h +31 -0
  154. data/vendor/NTRUplus/NTRU+864/randombytes.h +9 -0
  155. data/vendor/NTRUplus/NTRU+864/symmetric.c +39 -0
  156. data/vendor/NTRUplus/NTRU+864/symmetric.h +12 -0
  157. data/vendor/SMAUG-T/LICENSE +22 -0
  158. data/vendor/SMAUG-T/include/api.h +37 -0
  159. data/vendor/SMAUG-T/include/cbd.h +15 -0
  160. data/vendor/SMAUG-T/include/ciphertext.h +45 -0
  161. data/vendor/SMAUG-T/include/common.h +12 -0
  162. data/vendor/SMAUG-T/include/config.h +48 -0
  163. data/vendor/SMAUG-T/include/dg.h +28 -0
  164. data/vendor/SMAUG-T/include/fips202.h +41 -0
  165. data/vendor/SMAUG-T/include/hash.h +21 -0
  166. data/vendor/SMAUG-T/include/hwt.h +28 -0
  167. data/vendor/SMAUG-T/include/indcpa.h +33 -0
  168. data/vendor/SMAUG-T/include/key.h +34 -0
  169. data/vendor/SMAUG-T/include/pack.h +78 -0
  170. data/vendor/SMAUG-T/include/packring.h +50 -0
  171. data/vendor/SMAUG-T/include/params.h +84 -0
  172. data/vendor/SMAUG-T/include/poly.h +41 -0
  173. data/vendor/SMAUG-T/include/randombytes.h +11 -0
  174. data/vendor/SMAUG-T/include/toomcook.h +14 -0
  175. data/vendor/SMAUG-T/include/verify.h +16 -0
  176. data/vendor/SMAUG-T/src/cbd.c +159 -0
  177. data/vendor/SMAUG-T/src/ciphertext.c +95 -0
  178. data/vendor/SMAUG-T/src/dg.c +112 -0
  179. data/vendor/SMAUG-T/src/fips202.c +745 -0
  180. data/vendor/SMAUG-T/src/hash.c +15 -0
  181. data/vendor/SMAUG-T/src/hwt.c +121 -0
  182. data/vendor/SMAUG-T/src/indcpa.c +187 -0
  183. data/vendor/SMAUG-T/src/kem.c +194 -0
  184. data/vendor/SMAUG-T/src/key.c +102 -0
  185. data/vendor/SMAUG-T/src/pack.c +349 -0
  186. data/vendor/SMAUG-T/src/packring.c +503 -0
  187. data/vendor/SMAUG-T/src/poly.c +200 -0
  188. data/vendor/SMAUG-T/src/toomcook.c +256 -0
  189. data/vendor/SMAUG-T/src/verify.c +48 -0
  190. data/vendor/SOURCES.json +130 -0
  191. metadata +280 -0
@@ -0,0 +1,371 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ #include "poly.h"
4
+ #include "decompose.h"
5
+ #include "ntt.h"
6
+ #include "params.h"
7
+ #include "reduce.h"
8
+ #include "sampler.h"
9
+ #include "symmetric.h"
10
+
11
+ #include <stdint.h>
12
+
13
+ /*************************************************
14
+ * Name: poly_add
15
+ *
16
+ * Description: Add polynomials. No modular reduction is performed.
17
+ *
18
+ * Arguments: - poly *c: pointer to output polynomial
19
+ * - const poly *a: pointer to first summand
20
+ * - const poly *b: pointer to second summand
21
+ **************************************************/
22
+ void poly_add(poly *c, const poly *a, const poly *b) {
23
+ unsigned int i;
24
+
25
+ for (i = 0; i < HAETAE_N; ++i)
26
+ c->coeffs[i] = a->coeffs[i] + b->coeffs[i];
27
+ }
28
+
29
+ /*************************************************
30
+ * Name: poly_sub
31
+ *
32
+ * Description: Subtract polynomials. No modular reduction is
33
+ * performed.
34
+ *
35
+ * Arguments: - poly *c: pointer to output polynomial
36
+ * - const poly *a: pointer to first input polynomial
37
+ * - const poly *b: pointer to second input polynomial to be
38
+ * subtraced from first input polynomial
39
+ **************************************************/
40
+ void poly_sub(poly *c, const poly *a, const poly *b) {
41
+ unsigned int i;
42
+
43
+ for (i = 0; i < HAETAE_N; ++i)
44
+ c->coeffs[i] = a->coeffs[i] - b->coeffs[i];
45
+ }
46
+
47
+ /*************************************************
48
+ * Name: poly_pointwise_montgomery
49
+ *
50
+ * Description: Pointwise multiplication of polynomials in NTT domain
51
+ * representation and multiplication of resulting polynomial
52
+ * by 2^{-32}.
53
+ *
54
+ * Arguments: - poly *c: pointer to output polynomial
55
+ * - const poly *a: pointer to first input polynomial
56
+ * - const poly *b: pointer to second input polynomial
57
+ **************************************************/
58
+ void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) {
59
+ unsigned int i;
60
+
61
+ for (i = 0; i < HAETAE_N; ++i)
62
+ c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]);
63
+ }
64
+
65
+ /*************************************************
66
+ * Name: poly_reduce2q
67
+ *
68
+ * Description: Inplace reduction of all coefficients of polynomial to 2q
69
+ *
70
+ * Arguments: - poly *a: pointer to input/output polynomial
71
+ **************************************************/
72
+ void poly_reduce2q(poly *a) {
73
+ unsigned int i;
74
+
75
+ for (i = 0; i < HAETAE_N; ++i)
76
+ a->coeffs[i] = reduce32_2q(a->coeffs[i]);
77
+ }
78
+
79
+ /*************************************************
80
+ * Name: poly_freeze2q
81
+ *
82
+ * Description: For all coefficients of in/out polynomial compute standard
83
+ * representative r = a mod^+ 2Q
84
+ *
85
+ * Arguments: - poly *a: pointer to input/output polynomial
86
+ **************************************************/
87
+ void poly_freeze2q(poly *a) {
88
+ unsigned int i;
89
+
90
+ for (i = 0; i < HAETAE_N; ++i)
91
+ a->coeffs[i] = freeze2q(a->coeffs[i]);
92
+ }
93
+
94
+ /*************************************************
95
+ * Name: poly_freeze
96
+ *
97
+ * Description: For all coefficients of in/out polynomial compute standard
98
+ * representative r = a mod^+ HAETAE_Q
99
+ *
100
+ * Arguments: - poly *a: pointer to input/output polynomial
101
+ **************************************************/
102
+ void poly_freeze(poly *a) {
103
+ unsigned int i;
104
+
105
+ for (i = 0; i < HAETAE_N; ++i)
106
+ a->coeffs[i] = freeze(a->coeffs[i]);
107
+ }
108
+
109
+ /*************************************************
110
+ * Name: poly_highbits
111
+ *
112
+ * Description: Compute HighBits of polynomial
113
+ *
114
+ * Arguments: - poly *a2: pointer to output polynomial
115
+ * - const poly *a: pointer to input polynomial
116
+ **************************************************/
117
+ void poly_highbits(poly *a2, const poly *a) {
118
+ unsigned int i;
119
+ int32_t a1tmp;
120
+
121
+ for (i = 0; i < HAETAE_N; ++i)
122
+ decompose_z1(&a2->coeffs[i], &a1tmp, a->coeffs[i]);
123
+ }
124
+
125
+ /*************************************************
126
+ * Name: poly_lowbits
127
+ *
128
+ * Description: Compute LowBits of polynomial
129
+ *
130
+ * Arguments: - poly *a1: pointer to output polynomial
131
+ * - const poly *a: pointer to input polynomial
132
+ **************************************************/
133
+ void poly_lowbits(poly *a1, const poly *a) {
134
+ unsigned int i = 0;
135
+ int32_t a2tmp = 0;
136
+
137
+ for (i = 0; i < HAETAE_N; ++i)
138
+ decompose_z1(&a2tmp, &a1->coeffs[i], a->coeffs[i]);
139
+ }
140
+
141
+ /*************************************************
142
+ * Name: poly_compose
143
+ *
144
+ * Description: Compose HighBits and LowBits to recreate the polynomial
145
+ *
146
+ * Arguments: - poly *a3: pointer to output polynomial
147
+ * - const poly *ha: pointer to HighBits polynomial
148
+ * - const poly *la: pointer to HighBits polynomial
149
+ **************************************************/
150
+ void poly_compose(poly *a, const poly *ha, const poly *la) {
151
+ unsigned int i = 0;
152
+
153
+ for (i = 0; i < HAETAE_N; ++i)
154
+ a->coeffs[i] = (ha->coeffs[i] * 256) + la->coeffs[i];
155
+ }
156
+
157
+ /*************************************************
158
+ * Name: poly_lsb
159
+ *
160
+ * Description: Compute least significant bits of polynomial
161
+ *
162
+ * Arguments: - poly *a0: pointer to output polynomial
163
+ * - const poly *a: pointer to input polynomial
164
+ **************************************************/
165
+ void poly_lsb(poly *a0, const poly *a) {
166
+ unsigned int i;
167
+
168
+ for (i = 0; i < HAETAE_N; ++i)
169
+ a0->coeffs[i] = a->coeffs[i] & 1;
170
+ }
171
+
172
+ /*************************************************
173
+ * Name: poly_uniform
174
+ *
175
+ * Description: Sample polynomial with uniformly random coefficients
176
+ * in [0,Q-1] by performing rejection sampling on the
177
+ * output stream of SHAKE128(seed|nonce)
178
+ *
179
+ * Arguments: - poly *a: pointer to output polynomial
180
+ * - const uint8_t seed[]: byte array with seed of length
181
+ * HAETAE_SEEDBYTES
182
+ * - uint16_t nonce: 2-byte nonce
183
+ *
184
+ * Specification: Implements Algorithm 6, PolyUniform.
185
+ **************************************************/
186
+ #define POLY_UNIFORM_NBLOCKS \
187
+ ((512 + STREAM128_BLOCKBYTES - 1) / STREAM128_BLOCKBYTES)
188
+ // HAETAE_N * 2(random bytes for [0, HAETAE_Q - 1])
189
+
190
+ void poly_uniform(poly *a, const uint8_t seed[HAETAE_SEEDBYTES],
191
+ uint16_t nonce) {
192
+ unsigned int i, ctr, off;
193
+ unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES;
194
+ uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1];
195
+ stream128_state state;
196
+
197
+ stream128_init(&state, seed, nonce);
198
+ stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state);
199
+
200
+ ctr = rej_uniform(a->coeffs, HAETAE_N, buf, buflen);
201
+
202
+ while (ctr < HAETAE_N) {
203
+ off = buflen % 2;
204
+ for (i = 0; i < off; ++i)
205
+ buf[i] = buf[buflen - off + i];
206
+
207
+ stream128_squeezeblocks(buf + off, 1, &state);
208
+ buflen = STREAM128_BLOCKBYTES + off;
209
+ ctr += rej_uniform(a->coeffs + ctr, HAETAE_N - ctr, buf, buflen);
210
+ }
211
+ }
212
+
213
+ /*************************************************
214
+ * Name: poly_uniform_eta
215
+ *
216
+ * Description: Sample polynomial with uniformly random coefficients
217
+ * in [-ETA,ETA] by performing rejection sampling on the
218
+ * output stream from SHAKE256(seed|nonce)
219
+ *
220
+ * Arguments: - poly *a: pointer to output polynomial
221
+ * - const uint8_t seed[]: byte array with seed of length
222
+ * HAETAE_CRHBYTES
223
+ * - uint16_t nonce: 2-byte nonce
224
+ *
225
+ * Specification: Implements Algorithm 9, PolyUniformEta.
226
+ **************************************************/
227
+ #define POLY_UNIFORM_ETA_NBLOCKS \
228
+ ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) // 1
229
+
230
+ void poly_uniform_eta(poly *a, const uint8_t seed[HAETAE_CRHBYTES],
231
+ uint16_t nonce) {
232
+ unsigned int ctr;
233
+ unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES;
234
+ uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES];
235
+ stream256_state state;
236
+
237
+ stream256_init(&state, seed, nonce);
238
+ stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state);
239
+
240
+ ctr = rej_eta(a->coeffs, HAETAE_N, buf, buflen);
241
+
242
+ while (ctr < HAETAE_N) {
243
+ stream256_squeezeblocks(buf, 1, &state);
244
+ ctr += rej_eta(a->coeffs + ctr, HAETAE_N - ctr, buf, STREAM256_BLOCKBYTES);
245
+ }
246
+ }
247
+
248
+ uint8_t hammingWeight_8(uint8_t x) {
249
+ x = (x & 0x55) + (x >> 1 & 0x55);
250
+ x = (x & 0x33) + (x >> 2 & 0x33);
251
+ x = (x & 0x0F) + (x >> 4 & 0x0F);
252
+
253
+ return x;
254
+ }
255
+
256
+ /*************************************************
257
+ * Name: poly_challenge
258
+ *
259
+ * Description: Implementation of challenge. Samples polynomial with HAETAE_TAU
260
+ * 1 coefficients using the output stream of SHAKE256(seed).
261
+ *
262
+ * Arguments: - poly *c: pointer to output polynomial
263
+ * - const uint8_t highbits_lsb[]: packed highbits and lsb
264
+ * - const uint8_t mu[]: hash of vk and message
265
+ *
266
+ * Specification: Implements Algorithm 16, SampleChallenge.
267
+ **************************************************/
268
+ void poly_challenge(
269
+ poly *c,
270
+ const uint8_t highbits_lsb[HAETAE_POLYVECK_HIGHBITS_PACKEDBYTES +
271
+ HAETAE_POLYC_PACKEDBYTES],
272
+ const uint8_t mu[HAETAE_SEEDBYTES]) {
273
+ #if (HAETAE_MODE == HAETAE_MODE2) || (HAETAE_MODE == HAETAE_MODE3)
274
+ unsigned int i, b, pos = 0;
275
+ uint8_t buf[XOF256_BLOCKBYTES];
276
+ xof256_state state;
277
+
278
+ // H(HighBits(A * y mod 2q), LSB(round(y0) * j), HAETAE_M)
279
+ xof256_absorb_twice(&state, highbits_lsb,
280
+ HAETAE_POLYVECK_HIGHBITS_PACKEDBYTES +
281
+ HAETAE_POLYC_PACKEDBYTES,
282
+ mu, HAETAE_SEEDBYTES);
283
+ xof256_squeezeblocks(buf, 1, &state);
284
+
285
+ for (i = 0; i < HAETAE_N; ++i)
286
+ c->coeffs[i] = 0;
287
+ for (i = HAETAE_N - HAETAE_TAU; i < HAETAE_N; ++i) {
288
+ do {
289
+ if (pos >= XOF256_BLOCKBYTES) {
290
+ xof256_squeezeblocks(buf, 1, &state);
291
+ pos = 0;
292
+ }
293
+
294
+ b = buf[pos++];
295
+ } while (b > i);
296
+
297
+ c->coeffs[i] = c->coeffs[b];
298
+ c->coeffs[b] = 1;
299
+ }
300
+ #elif HAETAE_MODE == HAETAE_MODE5
301
+ unsigned int i, hwt = 0, cond = 0;
302
+ uint8_t mask = 0, w0 = 0;
303
+ uint8_t buf[32] = {0};
304
+ xof256_state state;
305
+
306
+ // H(HighBits(A * y mod 2q), LSB(round(y0) * j), HAETAE_M)
307
+ xof256_absorb_twice(&state, highbits_lsb,
308
+ HAETAE_POLYVECK_HIGHBITS_PACKEDBYTES +
309
+ HAETAE_POLYC_PACKEDBYTES,
310
+ mu, HAETAE_SEEDBYTES);
311
+ xof256_squeeze(buf, 32, &state);
312
+
313
+ for (i = 0; i < 32; ++i)
314
+ hwt += hammingWeight_8(buf[i]);
315
+
316
+ cond = (128 - hwt);
317
+ mask = 0xff & (cond >> 8);
318
+ w0 = -(buf[0] & 1);
319
+ mask = w0 ^ ((-(!!cond & 1)) & (mask ^ w0)); // mask = !!cond ? mask : w0
320
+ for (i = 0; i < 32; ++i) {
321
+ buf[i] ^= mask;
322
+ c->coeffs[8 * i] = buf[i] & 1;
323
+ c->coeffs[8 * i + 1] = (buf[i] >> 1) & 1;
324
+ c->coeffs[8 * i + 2] = (buf[i] >> 2) & 1;
325
+ c->coeffs[8 * i + 3] = (buf[i] >> 3) & 1;
326
+ c->coeffs[8 * i + 4] = (buf[i] >> 4) & 1;
327
+ c->coeffs[8 * i + 5] = (buf[i] >> 5) & 1;
328
+ c->coeffs[8 * i + 6] = (buf[i] >> 6) & 1;
329
+ c->coeffs[8 * i + 7] = (buf[i] >> 7) & 1;
330
+ }
331
+ #endif
332
+ }
333
+
334
+ void poly_decomposed_pack(uint8_t *buf, const poly *a) {
335
+ unsigned int i;
336
+ for (i = 0; i < HAETAE_N; i++) {
337
+ buf[i] = a->coeffs[i];
338
+ }
339
+ }
340
+
341
+ void poly_decomposed_unpack(poly *a, const uint8_t *buf) {
342
+ unsigned int i;
343
+ for (i = 0; i < HAETAE_N; i++) {
344
+ a->coeffs[i] = (int8_t)buf[i];
345
+ }
346
+ }
347
+
348
+ void poly_fromcrt(poly *w, const poly *u, const poly *v) {
349
+ unsigned int i;
350
+ int32_t xq, x2;
351
+
352
+ for (i = 0; i < HAETAE_N; i++) {
353
+ xq = u->coeffs[i];
354
+ x2 = v->coeffs[i];
355
+ w->coeffs[i] = xq + (HAETAE_Q & -((xq ^ x2) & 1));
356
+ }
357
+ }
358
+
359
+ void poly_fromcrt0(poly *w, const poly *u) {
360
+ unsigned int i;
361
+ int32_t xq;
362
+
363
+ for (i = 0; i < HAETAE_N; i++) {
364
+ xq = u->coeffs[i];
365
+ w->coeffs[i] = xq + (HAETAE_Q & -(xq & 1));
366
+ }
367
+ }
368
+
369
+ void poly_ntt(poly *a) { ntt(&a->coeffs[0]); }
370
+
371
+ void poly_invntt_tomont(poly *a) { invntt_tomont(&a->coeffs[0]); }
@@ -0,0 +1,298 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ #include "polyfix.h"
4
+ #include "fips202.h"
5
+ #include "fixpoint.h"
6
+ #include "params.h"
7
+ #include "sampler.h"
8
+
9
+ #include <stdint.h>
10
+
11
+ /*************************************************
12
+ * Name: polyfix_add
13
+ *
14
+ * Description: Add double polynomial and integer polynomial.
15
+ * No modular reduction is performed.
16
+ *
17
+ * Arguments: - polyfix *c: pointer to output double polynomial
18
+ * - const polyfix *a: pointer to first summand
19
+ * - const poly *b: pointer to second summand
20
+ **************************************************/
21
+ void polyfix_add(polyfix *c, const polyfix *a, const poly *b) {
22
+ unsigned int i;
23
+
24
+ for (i = 0; i < HAETAE_N; ++i)
25
+ c->coeffs[i] = a->coeffs[i] + HAETAE_LN * b->coeffs[i];
26
+ }
27
+
28
+ /*************************************************
29
+ * Name: polyfixfix_sub
30
+ *
31
+ * Description: Subtract fixed polynomial and fixed polynomial.
32
+ * No modular reduction is performed.
33
+ *
34
+ * Arguments: - polyfix *c: pointer to output fixed polynomial
35
+ * - const polyfix *a: pointer to first summand
36
+ * - const polyfix *b: pointer to second summand
37
+ **************************************************/
38
+ void polyfixfix_sub(polyfix *c, const polyfix *a, const polyfix *b) {
39
+ unsigned int i;
40
+
41
+ for (i = 0; i < HAETAE_N; ++i)
42
+ c->coeffs[i] = a->coeffs[i] - b->coeffs[i];
43
+ }
44
+
45
+ int32_t fix_round(int32_t num) {
46
+ return (num + HAETAE_LNHALF) >> HAETAE_LNBITS;
47
+ }
48
+
49
+ /*************************************************
50
+ * Name: polyfix_round
51
+ *
52
+ * Description: rounds a fixed polynomial to integer polynomial
53
+ *
54
+ * Arguments: - poly *a: output integer polynomial
55
+ * - poly *b: input fixed polynomial
56
+ **************************************************/
57
+ void polyfix_round(poly *a, const polyfix *b) {
58
+ unsigned i;
59
+
60
+ for (i = 0; i < HAETAE_N; ++i)
61
+ a->coeffs[i] = fix_round(b->coeffs[i]);
62
+ }
63
+
64
+ /*************************************************
65
+ * Name: polyfixveck_add
66
+ *
67
+ * Description: Add vector to a vector of double polynomials of length HAETAE_K.
68
+ * No modular reduction is performed.
69
+ *
70
+ * Arguments: - polyveck *w: pointer to output vector
71
+ * - const polyveck *u: pointer to first summand
72
+ * - const polyveck *v: pointer to second summand
73
+ **************************************************/
74
+ void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v) {
75
+ unsigned int i;
76
+
77
+ for (i = 0; i < HAETAE_K; ++i)
78
+ polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]);
79
+ }
80
+
81
+ /*************************************************
82
+ * Name: polyfixfixveck_sub
83
+ *
84
+ * Description: subtract vector to a vector of fixed polynomials of length k.
85
+ * No modular reduction is performed.
86
+ *
87
+ * Arguments: - polyveck *w: pointer to output vector
88
+ * - const polyfixveck *u: pointer to first summand
89
+ * - const polyfixveck *v: pointer to second summand
90
+ **************************************************/
91
+ void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u,
92
+ const polyfixveck *v) {
93
+ unsigned int i;
94
+
95
+ for (i = 0; i < HAETAE_K; ++i)
96
+ polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]);
97
+ }
98
+
99
+ /*************************************************
100
+ * Name: polyfixveck_double
101
+ *
102
+ * Description: Double vector of polynomials of length HAETAE_K.
103
+ *
104
+ * Arguments: - polyveck *b: pointer to output vector
105
+ * - polyveck *a: pointer to input vector
106
+ **************************************************/
107
+ void polyfixveck_double(polyfixveck *b, const polyfixveck *a) {
108
+ unsigned int i, j;
109
+
110
+ for (i = 0; i < HAETAE_K; ++i)
111
+ for (j = 0; j < HAETAE_N; ++j)
112
+ b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j];
113
+ }
114
+
115
+ /*************************************************
116
+ * Name: polyfixveck_round
117
+ *
118
+ * Description: rounds a fixed polynomial vector of length HAETAE_K
119
+ *
120
+ * Arguments: - polyveck *a: output integer polynomial vector
121
+ * - polyfixveck *b: input fixed polynomial vector
122
+ **************************************************/
123
+ void polyfixveck_round(polyveck *a, const polyfixveck *b) {
124
+ unsigned i;
125
+
126
+ for (i = 0; i < HAETAE_K; ++i)
127
+ polyfix_round(&a->vec[i], &b->vec[i]);
128
+ }
129
+
130
+ /*************************************************
131
+ * Name: polyfixvecl_add
132
+ *
133
+ * Description: Add vector to a vector of double polynomials of length L.
134
+ * No modular reduction is performed.
135
+ *
136
+ * Arguments: - polyvecl *w: pointer to output vector
137
+ * - const polyfixvecl *u: pointer to first summand
138
+ * - const polyvecl *v: pointer to second summand
139
+ **************************************************/
140
+ void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v) {
141
+ unsigned int i;
142
+
143
+ for (i = 0; i < HAETAE_L; ++i)
144
+ polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]);
145
+ }
146
+
147
+ /*************************************************
148
+ * Name: polyfixfixvecl_sub
149
+ *
150
+ * Description: subtract vector to a vector of fixed polynomials of length l.
151
+ * No modular reduction is performed.
152
+ *
153
+ * Arguments: - polyvecl *w: pointer to output vector
154
+ * - const polyfixvecl *u: pointer to first summand
155
+ * - const polyfixvecl *v: pointer to second summand
156
+ **************************************************/
157
+ void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u,
158
+ const polyfixvecl *v) {
159
+ unsigned int i;
160
+
161
+ for (i = 0; i < HAETAE_L; ++i)
162
+ polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]);
163
+ }
164
+ /*************************************************
165
+ * Name: polyfixvecl_double
166
+ *
167
+ * Description: Double vector of polynomials of length L.
168
+ *
169
+ * Arguments: - polyveck *b: pointer to output vector
170
+ * - polyveck *a: pointer to input vector
171
+ **************************************************/
172
+ void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a) {
173
+ unsigned int i, j;
174
+
175
+ for (i = 0; i < HAETAE_L; ++i)
176
+ for (j = 0; j < HAETAE_N; ++j)
177
+ b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j];
178
+ }
179
+
180
+ /*************************************************
181
+ * Name: polyfixvecl_round
182
+ *
183
+ * Description: rounds a fixed polynomial vector of length L
184
+ *
185
+ * Arguments: - polyvecl *a: output integer polynomial vector
186
+ * - polyfixvecl *b: input fixed polynomial vector
187
+ **************************************************/
188
+ void polyfixvecl_round(polyvecl *a, const polyfixvecl *b) {
189
+ unsigned i;
190
+
191
+ for (i = 0; i < HAETAE_L; ++i)
192
+ polyfix_round(&a->vec[i], &b->vec[i]);
193
+ }
194
+
195
+ /*************************************************
196
+ * Name: polyfixveclk_norm2
197
+ *
198
+ * Description: Calculates L2 norm of a fixed point polynomial vector with
199
+ * length HAETAE_L + HAETAE_K The result is L2 norm * HAETAE_LN
200
+ * similar to the way polynomial is usually stored
201
+ *
202
+ * Arguments: - polyfixvecl *a: polynomial vector with length HAETAE_L to
203
+ * calculate norm
204
+ * - polyfixveck *b: polynomial vector with length HAETAE_K to
205
+ * calculate norm
206
+ **************************************************/
207
+ uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b) {
208
+ unsigned int i, j;
209
+ uint64_t ret = 0;
210
+
211
+ for (i = 0; i < HAETAE_L; ++i) {
212
+ for (j = 0; j < HAETAE_N; ++j)
213
+ ret += (int64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j];
214
+ }
215
+
216
+ for (i = 0; i < HAETAE_K; ++i) {
217
+ for (j = 0; j < HAETAE_N; ++j)
218
+ ret += (int64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j];
219
+ }
220
+
221
+ return ret;
222
+ }
223
+
224
+ /*************************************************
225
+ * Name: polyfixveclk_sample_hyperball
226
+ *
227
+ * Description: sample hyperball
228
+ *
229
+ * Arguments: - polyfixvecl *y1: polynomial vector with length HAETAE_L to
230
+ * calculate norm
231
+ * - polyfixveck *y2: polynomial vector with length HAETAE_K to
232
+ * calculate norm
233
+ * - uint8_t *b: output byte
234
+ * - uint8_t seed[HAETAE_CRHBYTES]: input seed bytes
235
+ * - const uint16_t nonce: input nonce
236
+ *
237
+ * Specification: Implements Algorithm 11, SampleHyperBall.
238
+ **************************************************/
239
+ uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2,
240
+ uint8_t *b,
241
+ const uint8_t seed[HAETAE_CRHBYTES],
242
+ const uint16_t nonce) {
243
+ uint16_t ni = nonce;
244
+ uint64_t samples[HAETAE_N * (HAETAE_L + HAETAE_K)];
245
+ fp96_76 sqsum, invsqrt;
246
+ unsigned int i, j;
247
+ uint8_t signs[HAETAE_N * (HAETAE_L + HAETAE_K) / 8];
248
+
249
+ do {
250
+ sqsum.limb48[0] = 0;
251
+ sqsum.limb48[1] = 0;
252
+
253
+ sample_gauss_N(&samples[0], &signs[0], &sqsum, seed, ni++, HAETAE_N + 1);
254
+ sample_gauss_N(&samples[HAETAE_N], &signs[HAETAE_N / 8], &sqsum, seed, ni++,
255
+ HAETAE_N + 1);
256
+
257
+ for (i = 2; i < HAETAE_L + HAETAE_K; i++)
258
+ sample_gauss_N(&samples[HAETAE_N * i], &signs[HAETAE_N / 8 * i], &sqsum,
259
+ seed, ni++, HAETAE_N);
260
+
261
+ // divide sqsum by 2 and approximate inverse square root
262
+ sqsum.limb48[0] += 1; // rounding
263
+ sqsum.limb48[0] >>= 1;
264
+ sqsum.limb48[0] += (sqsum.limb48[1] & 1) << 47;
265
+ sqsum.limb48[1] >>= 1;
266
+ sqsum.limb48[1] += sqsum.limb48[0] >> 48;
267
+ sqsum.limb48[0] &= (1ULL << 48) - 1;
268
+ fixpoint_newton_invsqrt(&invsqrt, &sqsum);
269
+ fixpoint_mul_high(&sqsum, &invsqrt,
270
+ (uint64_t)(HAETAE_B0 * HAETAE_LN + HAETAE_SQNM / 2)
271
+ << (28 - 13));
272
+
273
+ for (i = 0; i < HAETAE_L; i++) {
274
+ for (j = 0; j < HAETAE_N; j++)
275
+ y1->vec[i].coeffs[j] = fixpoint_mul_rnd13(
276
+ samples[(i * HAETAE_N + j)], &sqsum,
277
+ (signs[(i * HAETAE_N + j) / 8] >> ((i * HAETAE_N + j) % 8)) & 1);
278
+ }
279
+ for (i = HAETAE_L; i < HAETAE_K + HAETAE_L; i++) {
280
+ for (j = 0; j < HAETAE_N; j++)
281
+ y2->vec[i - HAETAE_L].coeffs[j] = fixpoint_mul_rnd13(
282
+ samples[(i * HAETAE_N + j)], &sqsum,
283
+ (signs[(i * HAETAE_N + j) / 8] >> ((i * HAETAE_N + j) % 8)) & 1);
284
+ }
285
+ } while (polyfixveclk_sqnorm2(y1, y2) > HAETAE_B0SQ * HAETAE_LN * HAETAE_LN);
286
+
287
+ {
288
+ uint8_t tmp[HAETAE_CRHBYTES + 2];
289
+ for (i = 0; i < HAETAE_CRHBYTES; i++) {
290
+ tmp[i] = seed[i];
291
+ }
292
+ tmp[HAETAE_CRHBYTES + 0] = ni >> 0;
293
+ tmp[HAETAE_CRHBYTES + 1] = ni >> 8;
294
+ shake256(b, 1, tmp, HAETAE_CRHBYTES + 2);
295
+ }
296
+
297
+ return ni;
298
+ }