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,82 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ #include "polymat.h"
4
+ #include "params.h"
5
+ #include "poly.h"
6
+ #include "polyvec.h"
7
+
8
+ #include <stdint.h>
9
+
10
+ /*************************************************
11
+ * Name: polymatkl_expand_matA
12
+ *
13
+ * Description: Implementation of ExpandA. Generates matrix A with uniformly
14
+ * random coefficients a_{i,j} by performing rejection
15
+ * sampling on the output stream of SHAKE128(rho|j|i)
16
+ * or AES256CTR(rho,j|i).
17
+ *
18
+ * Arguments: - polyvecm mat[HAETAE_K]: output matrix k \times m
19
+ * - const uint8_t rho[]: byte array containing seed rho
20
+ *
21
+ * Specification: Implements Algorithm 4, ExpandMatA.
22
+ **************************************************/
23
+ void polymatkl_expand_matA(polyvecl mat[HAETAE_K],
24
+ const uint8_t rho[HAETAE_SEEDBYTES]) {
25
+ unsigned int i, j;
26
+
27
+ for (i = 0; i < HAETAE_K; ++i)
28
+ for (j = 0; j < HAETAE_M; ++j)
29
+ poly_uniform(&mat[i].vec[j + 1], rho, (i << 8) + j);
30
+ }
31
+
32
+ /*************************************************
33
+ * Name: polymatkm_expand_matA
34
+ *
35
+ * Description: Implementation of ExpandA. Generates matrix A with uniformly
36
+ * random coefficients a_{i,j} by performing rejection
37
+ * sampling on the output stream of SHAKE128(rho|j|i)
38
+ * or AES256CTR(rho,j|i).
39
+ *
40
+ * Arguments: - polyvecm mat[HAETAE_K]: output matrix k \times m
41
+ * - const uint8_t rho[]: byte array containing seed rho
42
+ *
43
+ * Specification: Implements Algorithm 4, ExpandMatA.
44
+ **************************************************/
45
+ void polymatkm_expand_matA(polyvecm mat[HAETAE_K],
46
+ const uint8_t rho[HAETAE_SEEDBYTES]) {
47
+ unsigned int i, j;
48
+
49
+ for (i = 0; i < HAETAE_K; ++i)
50
+ for (j = 0; j < HAETAE_M; ++j)
51
+ poly_uniform(&mat[i].vec[j], rho, (i << 8) + j);
52
+ }
53
+
54
+ // doubles k * m sub-matrix of k * l mat
55
+ void polymatkl_double(polyvecl mat[HAETAE_K]) {
56
+ unsigned int i, j, k;
57
+ for (i = 0; i < HAETAE_K; ++i) {
58
+ for (j = 1; j < HAETAE_L; ++j) {
59
+ for (k = 0; k < HAETAE_N; ++k) {
60
+ mat[i].vec[j].coeffs[k] *= 2;
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[HAETAE_K],
67
+ const polyvecl *v) {
68
+ unsigned int i;
69
+
70
+ for (i = 0; i < HAETAE_K; ++i) {
71
+ polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v);
72
+ }
73
+ }
74
+
75
+ void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[HAETAE_K],
76
+ const polyvecm *v) {
77
+ unsigned int i;
78
+
79
+ for (i = 0; i < HAETAE_K; ++i) {
80
+ polyvecm_pointwise_acc_montgomery(&t->vec[i], &mat[i], v);
81
+ }
82
+ }
@@ -0,0 +1,534 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ #include "polyvec.h"
4
+ #include "decompose.h"
5
+ #include "fft.h"
6
+ #include "params.h"
7
+ #include "poly.h"
8
+ #include "reduce.h"
9
+
10
+ #include <stddef.h>
11
+ #include <stdint.h>
12
+
13
+ /*************************************************
14
+ * Name: polyveck_add
15
+ *
16
+ * Description: Add vectors of polynomials of length HAETAE_K.
17
+ * No modular reduction is performed.
18
+ *
19
+ * Arguments: - polyveck *w: pointer to output vector
20
+ * - const polyveck *u: pointer to first summand
21
+ * - const polyveck *v: pointer to second summand
22
+ **************************************************/
23
+ void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) {
24
+ unsigned int i;
25
+
26
+ for (i = 0; i < HAETAE_K; ++i)
27
+ poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
28
+ }
29
+
30
+ /*************************************************
31
+ * Name: polyveck_sub
32
+ *
33
+ * Description: Subtract vectors of polynomials of length HAETAE_K.
34
+ * No modular reduction is performed.
35
+ *
36
+ * Arguments: - polyveck *w: pointer to output vector
37
+ * - const polyveck *u: pointer to first input vector
38
+ * - const polyveck *v: pointer to second input vector to be
39
+ * subtracted from first input vector
40
+ **************************************************/
41
+ void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) {
42
+ unsigned int i;
43
+
44
+ for (i = 0; i < HAETAE_K; ++i)
45
+ poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]);
46
+ }
47
+
48
+ /*************************************************
49
+ * Name: polyveck_double
50
+ *
51
+ * Description: Double vector of polynomials of length HAETAE_K.
52
+ * No modular reduction is performed.
53
+ *
54
+ * Arguments: - polyveck *w: pointer to output vector
55
+ **************************************************/
56
+ void polyveck_double(polyveck *b) {
57
+ unsigned int i, j;
58
+
59
+ for (i = 0; i < HAETAE_K; ++i)
60
+ for (j = 0; j < HAETAE_N; ++j)
61
+ b->vec[i].coeffs[j] *= 2;
62
+ }
63
+
64
+ /*************************************************
65
+ * Name: polyveck_reduce2q
66
+ *
67
+ * Description: Reduce coefficients to 2q
68
+ *
69
+ * Arguments: - polyveck *v: pointer to input/output vector
70
+ **************************************************/
71
+ void polyveck_reduce2q(polyveck *v) {
72
+ unsigned int i;
73
+
74
+ for (i = 0; i < HAETAE_K; ++i)
75
+ poly_reduce2q(&v->vec[i]);
76
+ }
77
+
78
+ /*************************************************
79
+ * Name: polyveck_freeze
80
+ *
81
+ * Description: For all coefficients of polynomials in vector of length HAETAE_K
82
+ * compute standard representative r = a mod^+ HAETAE_Q.
83
+ *
84
+ * Arguments: - polyveck *v: pointer to input/output vector
85
+ **************************************************/
86
+ void polyveck_freeze(polyveck *v) {
87
+ unsigned int i;
88
+
89
+ for (i = 0; i < HAETAE_K; ++i)
90
+ poly_freeze(&v->vec[i]);
91
+ }
92
+
93
+ /*************************************************
94
+ * Name: polyveck_freeze2q
95
+ *
96
+ * Description: For all coefficients of polynomials in vector of length HAETAE_K
97
+ * compute standard representative r = a mod^+ 2Q.
98
+ *
99
+ * Arguments: - polyveck *v: pointer to input/output vector
100
+ **************************************************/
101
+ void polyveck_freeze2q(polyveck *v) {
102
+ unsigned int i;
103
+
104
+ for (i = 0; i < HAETAE_K; ++i)
105
+ poly_freeze2q(&v->vec[i]);
106
+ }
107
+
108
+ /*************************************************
109
+ * Name: polyveck_expand_vecA
110
+ *
111
+ * Description: Sample a vector of polynomials with uniformly random
112
+ * coefficients in Zq by rejection sampling on the
113
+ * output stream from SHAKE128(seed|nonce)
114
+ *
115
+ * Arguments: - polyveck *v: pointer to output a vector of polynomials of
116
+ * length HAETAE_K
117
+ * - const uint8_t seed[]: byte array with seed of length
118
+ * HAETAE_SEEDBYTES
119
+ *
120
+ * Specification: Implements Algorithm 5, ExpandVec_a.
121
+ **************************************************/
122
+ void polyveck_expand_vecA(polyveck *v, const uint8_t seed[HAETAE_SEEDBYTES]) {
123
+ unsigned int i, nonce = (HAETAE_K << 8) + HAETAE_M;
124
+ for (i = 0; i < HAETAE_K; ++i)
125
+ poly_uniform(&v->vec[i], seed, nonce++);
126
+ }
127
+
128
+ /*************************************************
129
+ * Name: polyvecmk_expand_S
130
+ *
131
+ * Description: Sample a vector of polynomials with uniformly random
132
+ * coefficients in [-ETA,ETA] by rejection sampling on the
133
+ * output stream from SHAKE256(seed|nonce)
134
+ *
135
+ * Arguments: - polyveck *v: pointer to output a vector of polynomials of
136
+ * length HAETAE_K
137
+ * - const uint8_t seed[]: byte array with seed of length
138
+ * HAETAE_CRHBYTES
139
+ * - uint16_t nonce: 2-byte nonce
140
+ *
141
+ * Specification: Implements Algorithm 8, ExpandS.
142
+ **************************************************/
143
+ void polyvecmk_expand_S(polyvecm *u, polyveck *v,
144
+ const uint8_t seed[HAETAE_CRHBYTES], uint16_t nonce) {
145
+ unsigned int i, n = nonce;
146
+ for (i = 0; i < HAETAE_M; i++)
147
+ poly_uniform_eta(&u->vec[i], seed, n++);
148
+ for (i = 0; i < HAETAE_K; ++i)
149
+ poly_uniform_eta(&v->vec[i], seed, n++);
150
+ }
151
+
152
+ /*************************************************
153
+ * Name: polyveck_double_negate
154
+ *
155
+ * Description: multiply each coefficient with -2
156
+ *
157
+ * Arguments: - polyveck *v: pointer to output vector of polynomials of
158
+ * length HAETAE_K
159
+ **************************************************/
160
+ void polyveck_double_negate(polyveck *v) {
161
+ unsigned int i, j;
162
+
163
+ for (i = 0; i < HAETAE_K; ++i)
164
+ for (j = 0; j < HAETAE_N; j++)
165
+ v->vec[i].coeffs[j] =
166
+ montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONT * -2);
167
+ }
168
+
169
+ /*************************************************
170
+ * Name: polyveck_frommont
171
+ *
172
+ * Description: multiply each coefficient with MONT
173
+ *
174
+ * Arguments: - polyveck *v: pointer to output vector of polynomials of
175
+ * length HAETAE_K
176
+ **************************************************/
177
+ void polyveck_frommont(polyveck *v) {
178
+ unsigned int i, j;
179
+
180
+ for (i = 0; i < HAETAE_K; ++i)
181
+ for (j = 0; j < HAETAE_N; j++)
182
+ v->vec[i].coeffs[j] =
183
+ montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONTSQ);
184
+ }
185
+
186
+ void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u,
187
+ const poly *v) {
188
+ unsigned int i;
189
+ for (i = 0; i < HAETAE_K; i++) {
190
+ poly_pointwise_montgomery(&w->vec[i], &u->vec[i], v);
191
+ }
192
+ }
193
+
194
+ /*************************************************
195
+ * Name: polyveck_poly_fromcrt
196
+ *
197
+ * Description: recover polynomials from CRT domain, where all "mod q"
198
+ * polynomials are known and only the uppermost "mod 2" polynomial
199
+ * is non-zero
200
+ *
201
+ * Arguments: - polyveck *w: pointer to output vector of polynomials of
202
+ * length HAETAE_K
203
+ * - const polyveck *u: pointer to the input vector of polynomials
204
+ * of length HAETAE_K
205
+ * - const poly *v: pointer to the input polynomial ("mod 2")
206
+ **************************************************/
207
+ void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v) {
208
+ unsigned int i;
209
+
210
+ poly_fromcrt(&w->vec[0], &u->vec[0], v);
211
+
212
+ for (i = 1; i < HAETAE_K; i++) {
213
+ poly_fromcrt0(&w->vec[i], &u->vec[i]);
214
+ }
215
+ }
216
+
217
+ void polyveck_highbits_hint(polyveck *w, const polyveck *v) {
218
+ unsigned int i, j;
219
+ for (i = 0; i < HAETAE_K; i++) {
220
+ for (j = 0; j < HAETAE_N; j++) {
221
+ decompose_hint(&w->vec[i].coeffs[j], v->vec[i].coeffs[j]);
222
+ }
223
+ }
224
+ }
225
+
226
+ void polyveck_cneg(polyveck *v, const uint8_t b) {
227
+ unsigned int i, j;
228
+ for (i = 0; i < HAETAE_K; i++) {
229
+ for (j = 0; j < HAETAE_N; j++) {
230
+ v->vec[i].coeffs[j] *= 1 - 2 * b;
231
+ }
232
+ }
233
+ }
234
+
235
+ void polyveck_caddDQ2ALPHA(polyveck *h) {
236
+ unsigned int i, j;
237
+ for (i = 0; i < HAETAE_K; i++) {
238
+ for (j = 0; j < HAETAE_N; j++) {
239
+ h->vec[i].coeffs[j] +=
240
+ (h->vec[i].coeffs[j] >> 31) & ((HAETAE_DQ - 2) / HAETAE_ALPHA_HINT);
241
+ }
242
+ }
243
+ }
244
+
245
+ void polyveck_csubDQ2ALPHA(polyveck *v) {
246
+ unsigned int i, j;
247
+ for (i = 0; i < HAETAE_K; i++) {
248
+ for (j = 0; j < HAETAE_N; j++) {
249
+ v->vec[i].coeffs[j] -=
250
+ ~((v->vec[i].coeffs[j] - (HAETAE_DQ - 2) / HAETAE_ALPHA_HINT) >> 31) &
251
+ ((HAETAE_DQ - 2) / HAETAE_ALPHA_HINT);
252
+ }
253
+ }
254
+ }
255
+
256
+ void polyveck_mul_alpha(polyveck *v, const polyveck *u) {
257
+ unsigned int i, j;
258
+ for (i = 0; i < HAETAE_K; i++) {
259
+ for (j = 0; j < HAETAE_N; j++) {
260
+ v->vec[i].coeffs[j] = u->vec[i].coeffs[j] * HAETAE_ALPHA_HINT;
261
+ }
262
+ }
263
+ }
264
+
265
+ void polyveck_div2(polyveck *v) {
266
+ unsigned i, j;
267
+ for (i = 0; i < HAETAE_K; ++i)
268
+ for (j = 0; j < HAETAE_N; ++j)
269
+ v->vec[i].coeffs[j] >>= 1;
270
+ }
271
+
272
+ void polyveck_caddq(polyveck *v) {
273
+ unsigned i, j;
274
+ for (i = 0; i < HAETAE_K; ++i)
275
+ for (j = 0; j < HAETAE_N; ++j)
276
+ v->vec[i].coeffs[j] = caddq(v->vec[i].coeffs[j]);
277
+ }
278
+
279
+ void polyveck_decompose_vk(polyveck *v0, polyveck *v) {
280
+ for (int i = 0; i < HAETAE_K; i++) {
281
+ for (int j = 0; j < HAETAE_N; j++) {
282
+ v->vec[i].coeffs[j] =
283
+ decompose_vk(&v0->vec[i].coeffs[j], v->vec[i].coeffs[j]);
284
+ }
285
+ }
286
+ }
287
+
288
+ void polyveck_ntt(polyveck *x) {
289
+ unsigned int i;
290
+ for (i = 0; i < HAETAE_K; i++) {
291
+ poly_ntt(&x->vec[i]);
292
+ }
293
+ }
294
+
295
+ void polyveck_invntt_tomont(polyveck *x) {
296
+ unsigned int i;
297
+ for (i = 0; i < HAETAE_K; i++) {
298
+ poly_invntt_tomont(&x->vec[i]);
299
+ }
300
+ }
301
+
302
+ /*************************************************
303
+ * Name: polyveck_sqnorm2
304
+ *
305
+ * Description: Calculates L2 norm of a polynomial vector with length k
306
+ *
307
+ * Arguments: - polyveck *b: polynomial vector with length k to calculate
308
+ * norm
309
+ **************************************************/
310
+ uint64_t polyveck_sqnorm2(const polyveck *b) {
311
+ unsigned int i, j;
312
+ uint64_t ret = 0;
313
+
314
+ for (i = 0; i < HAETAE_K; ++i) {
315
+ for (j = 0; j < HAETAE_N; ++j) {
316
+ ret += (uint64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j];
317
+ }
318
+ }
319
+ return ret;
320
+ }
321
+
322
+ /*************************************************
323
+ * Name: polyvecl_highbits
324
+ *
325
+ * Description: Compute HighBits of a vector of polynomials
326
+ *
327
+ * Arguments: - polyvecl *v2: pointer to output vector of polynomials of
328
+ * length L
329
+ * - const polyvecl *v: pointer to input vector of polynomials of
330
+ * length L
331
+ **************************************************/
332
+ void polyvecl_highbits(polyvecl *v2, const polyvecl *v) {
333
+ unsigned int i;
334
+
335
+ for (i = 0; i < HAETAE_L; ++i)
336
+ poly_highbits(&v2->vec[i], &v->vec[i]);
337
+ }
338
+
339
+ /*************************************************
340
+ * Name: polyvecl_lowbits
341
+ *
342
+ * Description: Compute LowBits of a vector of polynomials
343
+ *
344
+ * Arguments: - polyvecl *v1: pointer to output vector of polynomials of
345
+ * length L
346
+ * - const polyvecl *v: pointer to input vector of polynomials of
347
+ * length L
348
+ **************************************************/
349
+ void polyvecl_lowbits(polyvecl *v1, const polyvecl *v) {
350
+ unsigned int i;
351
+
352
+ for (i = 0; i < HAETAE_L; ++i)
353
+ poly_lowbits(&v1->vec[i], &v->vec[i]);
354
+ }
355
+
356
+ void polyvecl_cneg(polyvecl *v, const uint8_t b) {
357
+ unsigned int i, j;
358
+ for (i = 0; i < HAETAE_L; i++) {
359
+ for (j = 0; j < HAETAE_N; j++) {
360
+ v->vec[i].coeffs[j] *= 1 - 2 * b;
361
+ }
362
+ }
363
+ }
364
+
365
+ /*************************************************
366
+ * Name: polyvecl_sqnorm2
367
+ *
368
+ * Description: Calculates L2 norm of a polynomial vector with length l
369
+ *
370
+ * Arguments: - polyvecl *a: polynomial vector with length l to calculate
371
+ * norm
372
+ **************************************************/
373
+ uint64_t polyvecl_sqnorm2(const polyvecl *a) {
374
+ unsigned int i, j;
375
+ uint64_t ret = 0;
376
+
377
+ for (i = 0; i < HAETAE_L; ++i) {
378
+ for (j = 0; j < HAETAE_N; ++j) {
379
+ ret += (uint64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j];
380
+ }
381
+ }
382
+
383
+ return ret;
384
+ }
385
+
386
+ /*************************************************
387
+ * Name: polyvecl_pointwise_acc_montgomery
388
+ *
389
+ * Description: Pointwise multiply vectors of polynomials of length L, multiply
390
+ * resulting vector by 2^{-32} and add (accumulate) polynomials
391
+ * in it. Input/output vectors are in NTT domain representation.
392
+ *
393
+ * Arguments: - poly *w: output polynomial
394
+ * - const polyvecl *u: pointer to first input vector
395
+ * - const polyvecl *v: pointer to second input vector
396
+ **************************************************/
397
+ void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u,
398
+ const polyvecl *v) {
399
+ unsigned int i;
400
+ poly t;
401
+
402
+ poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]);
403
+ for (i = 1; i < HAETAE_L; ++i) {
404
+ poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]);
405
+ poly_add(w, w, &t);
406
+ }
407
+ }
408
+
409
+ void polyvecl_ntt(polyvecl *x) {
410
+ unsigned int i;
411
+ for (i = 0; i < HAETAE_L; i++) {
412
+ poly_ntt(&x->vec[i]);
413
+ }
414
+ }
415
+
416
+ /*************************************************
417
+ * Name: polyvecm_pointwise_acc_montgomery
418
+ *
419
+ * Description: Pointwise multiply vectors of polynomials of length L, multiply
420
+ * resulting vector by 2^{-32} and add (accumulate) polynomials
421
+ * in it. Input/output vectors are in NTT domain representation.
422
+ *
423
+ * Arguments: - poly *w: output polynomial
424
+ * - const polyvecm *u: pointer to first input vector
425
+ * - const polyvecm *v: pointer to second input vector
426
+ **************************************************/
427
+ void polyvecm_pointwise_acc_montgomery(poly *w, const polyvecm *u,
428
+ const polyvecm *v) {
429
+ unsigned int i;
430
+ poly t;
431
+
432
+ poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]);
433
+ for (i = 1; i < HAETAE_M; ++i) {
434
+ poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]);
435
+ poly_add(w, w, &t);
436
+ }
437
+ }
438
+
439
+ void polyvecm_ntt(polyvecm *x) {
440
+ unsigned int i;
441
+ for (i = 0; i < HAETAE_M; i++) {
442
+ poly_ntt(&x->vec[i]);
443
+ }
444
+ }
445
+
446
+ /*************************************************
447
+ * Name: minmax
448
+ *
449
+ * Description: compare and swap two integers
450
+ *
451
+ * Arguments: - int32_t *x: pointer to first input/output integer
452
+ * - int32_t *y: pointer to second input/output integer
453
+ *
454
+ * Specification: Implements Algorithm 44, minmax.
455
+ * **************************************************/
456
+ static inline void minmax(int32_t *x, int32_t *y) // taken from djbsort
457
+ {
458
+ int32_t a = *x;
459
+ int32_t b = *y;
460
+ int32_t ab = b ^ a;
461
+ int32_t c = b - a;
462
+ c ^= ab & (c ^ b);
463
+ c >>= 31;
464
+ c &= ab;
465
+ *x = a ^ c;
466
+ *y = b ^ c;
467
+ }
468
+ /*************************************************
469
+ * Name: polyvecmk_sk_singular_value
470
+ *
471
+ * Description: calculate singular value of signing key
472
+ *
473
+ * Arguments: - const polyvecm *s1: pointer to first input vector
474
+ * - const polyveck *s2: pointer to second input vector
475
+ *
476
+ * Returns:
477
+ *
478
+ * Specification: Implements Algorithm 42, skSingularValue.
479
+ **************************************************/
480
+ int64_t polyvecmk_sk_singular_value(const polyvecm *s1, const polyveck *s2) {
481
+ int32_t res = 0;
482
+ complex_fp32_16 input[FFT_N] = {0};
483
+ int32_t sum[HAETAE_N] = {0}, bestm[HAETAE_N / HAETAE_TAU + 1] = {0}, min = 0;
484
+
485
+ for (size_t i = 0; i < HAETAE_M; ++i) {
486
+ fft_init_and_bitrev(input, &s1->vec[i]);
487
+ fft(input);
488
+ // cumulative sum
489
+ for (size_t j = 0; j < HAETAE_N; j++) {
490
+ sum[j] += complex_fp_sqabs(input[j]);
491
+ }
492
+ }
493
+
494
+ for (size_t i = 0; i < HAETAE_K; ++i) {
495
+ fft_init_and_bitrev(input, &s2->vec[i]);
496
+ fft(input);
497
+
498
+ // cumulative sum
499
+ for (size_t j = 0; j < HAETAE_N; j++) {
500
+ sum[j] += complex_fp_sqabs(input[j]);
501
+ }
502
+ }
503
+
504
+ // compute max m
505
+ for (size_t i = 0; i < HAETAE_N / HAETAE_TAU + 1; ++i) {
506
+ bestm[i] = sum[i];
507
+ }
508
+ for (size_t i = HAETAE_N / HAETAE_TAU + 1; i < HAETAE_N; i++) {
509
+ for (size_t j = 0; j < HAETAE_N / HAETAE_TAU + 1; j++) {
510
+ minmax(&sum[i], &bestm[j]);
511
+ }
512
+ }
513
+ // find minimum in bestm
514
+ min = bestm[0];
515
+ for (size_t i = 1; i < HAETAE_N / HAETAE_TAU + 1; i++) {
516
+ int32_t tmp = bestm[i];
517
+ minmax(&min, &tmp);
518
+ }
519
+ // multiply all but the minimum by HAETAE_N mod HAETAE_TAU
520
+ for (size_t i = 0; i < HAETAE_N / HAETAE_TAU + 1; i++) {
521
+ int32_t fac =
522
+ ((min - bestm[i]) >>
523
+ 31); // all-ones if bestm[i] != min
524
+ fac = (fac & (HAETAE_TAU)) ^
525
+ ((~fac) & (HAETAE_N % HAETAE_TAU)); // fac = HAETAE_TAU for all != min
526
+ // and N%HAETAE_TAU for min
527
+ bestm[i] += 0x10200; // add 1 for the "1 poly" in S, and prepare rounding
528
+ bestm[i] >>= 10; // round off 10 bits
529
+ bestm[i] *= fac;
530
+ res += bestm[i];
531
+ }
532
+
533
+ return (res + (1 << 5)) >> 6; // return rounded, squared value
534
+ }
@@ -0,0 +1,96 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ #include "reduce.h"
4
+ #include "params.h"
5
+
6
+ #include <stdint.h>
7
+
8
+ /*************************************************
9
+ * Name: montgomery_reduce
10
+ *
11
+ * Description: For finite field element a with -2^{31}Q <= a <= HAETAE_Q*2^31,
12
+ * compute r \equiv a*2^{-32} (mod HAETAE_Q) such that -HAETAE_Q <
13
+ * r < HAETAE_Q.
14
+ *
15
+ * Arguments: - int64_t: finite field element a
16
+ *
17
+ * Returns r.
18
+ **************************************************/
19
+ int32_t montgomery_reduce(int64_t a) {
20
+ int32_t t;
21
+
22
+ t = (int64_t)(int32_t)a * QINV;
23
+ t = (a - (int64_t)t * HAETAE_Q) >> 32;
24
+ return t;
25
+ }
26
+
27
+ /*************************************************
28
+ * Name: caddq
29
+ *
30
+ * Description: Add HAETAE_Q if input coefficient is negative.
31
+ *
32
+ * Arguments: - int32_t: finite field element a
33
+ *
34
+ * Returns r.
35
+ **************************************************/
36
+ int32_t caddq(int32_t a) {
37
+ a += (a >> 31) & HAETAE_Q;
38
+ return a;
39
+ }
40
+
41
+ /*************************************************
42
+ * Name: freeze
43
+ *
44
+ * Description: For finite field element a, compute standard
45
+ * representative r = a mod^+ HAETAE_Q.
46
+ *
47
+ * Arguments: - int32_t: finite field element a
48
+ *
49
+ * Returns r.
50
+ **************************************************/
51
+ int32_t freeze(int32_t a) {
52
+ int64_t t = (int64_t)a * QREC;
53
+ t = t >> 32;
54
+ t = a - t * HAETAE_Q; // -2Q < t < 2Q
55
+ t += (t >> 31) & HAETAE_DQ; // 0 <= t < 2Q
56
+ t -= ~((t - HAETAE_Q) >> 31) & HAETAE_Q; // 0 <= t < HAETAE_Q
57
+ return t;
58
+ }
59
+
60
+ /*************************************************
61
+ * Name: reduce32_2q
62
+ *
63
+ * Description: compute reduction with 2Q
64
+ *
65
+ * Arguments: - int32_t: finite field element a
66
+ *
67
+ * Returns r.
68
+ **************************************************/
69
+ int32_t reduce32_2q(int32_t a) {
70
+ int64_t t = (int64_t)a * DQREC;
71
+ t >>= 32;
72
+ t = a - t * HAETAE_DQ; // -4Q < t < 4Q
73
+ t += (t >> 31) & (HAETAE_DQ * 2); // 0 <= t < 4Q
74
+ t -= ~((t - HAETAE_DQ) >> 31) & HAETAE_DQ; // 0 <= t < HAETAE_Q
75
+ t -= ~((t - HAETAE_Q) >> 31) & HAETAE_DQ; // centered representation
76
+ return (int32_t)t;
77
+ }
78
+
79
+ /*************************************************
80
+ * Name: freeze2q
81
+ *
82
+ * Description: For finite field element a, compute standard
83
+ * representative r = a mod^+ 2Q.
84
+ *
85
+ * Arguments: - int32_t: finite field element a
86
+ *
87
+ * Returns r.
88
+ **************************************************/
89
+ int32_t freeze2q(int32_t a) {
90
+ int64_t t = (int64_t)a * DQREC;
91
+ t >>= 32;
92
+ t = a - t * HAETAE_DQ; // -4Q < t < 4Q
93
+ t += (t >> 31) & (HAETAE_DQ * 2); // 0 <= t < 4Q
94
+ t -= ~((t - HAETAE_DQ) >> 31) & HAETAE_DQ; // 0 <= t < HAETAE_Q
95
+ return (int32_t)t;
96
+ }