kpqc 0.1.0 → 0.2.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/Gemfile +4 -0
  4. data/README.md +9 -6
  5. data/THIRD_PARTY_NOTICES.md +14 -47
  6. data/ext/kpqc/extconf_helper.rb +6 -3
  7. data/ext/kpqc/secure_clear.c +8 -0
  8. data/kpqc.gemspec +4 -5
  9. data/lib/kpqc/aimer.rb +6 -6
  10. data/lib/kpqc/version.rb +1 -2
  11. data/test/kat/aimer128f.rsp +4 -4
  12. data/test/kat/aimer128s.rsp +4 -4
  13. data/test/kat/aimer192f.rsp +4 -4
  14. data/test/kat/aimer192s.rsp +4 -4
  15. data/test/kat/aimer256f.rsp +4 -4
  16. data/test/kat/aimer256s.rsp +4 -4
  17. data/test/kat/haetae2.rsp +1 -1
  18. data/test/kat/haetae3.rsp +1 -1
  19. data/test/kat/haetae5.rsp +1 -1
  20. data/vendor/AIMer/LICENSE +1 -1
  21. data/vendor/AIMer/aim3.c +227 -0
  22. data/vendor/AIMer/aim3.h +63 -0
  23. data/vendor/AIMer/field.h +12 -4
  24. data/vendor/AIMer/field128.c +24 -381
  25. data/vendor/AIMer/field192.c +24 -400
  26. data/vendor/AIMer/field256.c +28 -447
  27. data/vendor/AIMer/field_common.c +98 -0
  28. data/vendor/AIMer/field_internal.h +218 -0
  29. data/vendor/AIMer/params/params-aimer-128f.h +8 -8
  30. data/vendor/AIMer/params/params-aimer-128s.h +8 -8
  31. data/vendor/AIMer/params/params-aimer-192f.h +8 -8
  32. data/vendor/AIMer/params/params-aimer-192s.h +8 -8
  33. data/vendor/AIMer/params/params-aimer-256f.h +8 -8
  34. data/vendor/AIMer/params/params-aimer-256s.h +8 -8
  35. data/vendor/AIMer/params.h +5 -0
  36. data/vendor/AIMer/sign.c +246 -167
  37. data/vendor/AIMer/sign.h +6 -6
  38. data/vendor/AIMer/tree.c +10 -4
  39. data/vendor/AIMer/tree.h +1 -1
  40. data/vendor/HAETAE/include/fixpoint.h +14 -14
  41. data/vendor/HAETAE/include/rans_byte.h +10 -9
  42. data/vendor/HAETAE/src/decompose.c +8 -4
  43. data/vendor/HAETAE/src/encoding.c +5 -5
  44. data/vendor/HAETAE/src/fft.c +1 -1
  45. data/vendor/HAETAE/src/fips202.c +26 -14
  46. data/vendor/HAETAE/src/fixpoint.c +21 -18
  47. data/vendor/HAETAE/src/ntt.c +2 -0
  48. data/vendor/HAETAE/src/packing.c +15 -15
  49. data/vendor/HAETAE/src/poly.c +30 -3
  50. data/vendor/HAETAE/src/polyfix.c +2 -2
  51. data/vendor/HAETAE/src/polymat.c +2 -2
  52. data/vendor/HAETAE/src/polyvec.c +7 -5
  53. data/vendor/HAETAE/src/reduce.c +2 -0
  54. data/vendor/HAETAE/src/sampler.c +231 -47
  55. data/vendor/HAETAE/src/sign.c +11 -10
  56. data/vendor/NTRUplus/NTRU+1152/api.h +27 -8
  57. data/vendor/NTRUplus/NTRU+1152/fips202/fips202.c +12 -269
  58. data/vendor/NTRUplus/NTRU+1152/fips202/fips202.h +4 -113
  59. data/vendor/NTRUplus/NTRU+1152/kem.c +110 -40
  60. data/vendor/NTRUplus/NTRU+1152/ntt.c +50 -54
  61. data/vendor/NTRUplus/NTRU+1152/poly.c +21 -13
  62. data/vendor/NTRUplus/NTRU+1152/poly.h +3 -3
  63. data/vendor/NTRUplus/NTRU+1152/randombytes.h +1 -0
  64. data/vendor/NTRUplus/NTRU+1152/symmetric.c +3 -9
  65. data/vendor/NTRUplus/NTRU+1152/symmetric.h +13 -3
  66. data/vendor/NTRUplus/NTRU+1152/util.h +15 -0
  67. data/vendor/NTRUplus/NTRU+768/api.h +27 -8
  68. data/vendor/NTRUplus/NTRU+768/fips202/fips202.c +12 -269
  69. data/vendor/NTRUplus/NTRU+768/fips202/fips202.h +4 -113
  70. data/vendor/NTRUplus/NTRU+768/kem.c +110 -40
  71. data/vendor/NTRUplus/NTRU+768/ntt.c +50 -54
  72. data/vendor/NTRUplus/NTRU+768/poly.c +23 -13
  73. data/vendor/NTRUplus/NTRU+768/poly.h +3 -3
  74. data/vendor/NTRUplus/NTRU+768/randombytes.h +1 -0
  75. data/vendor/NTRUplus/NTRU+768/symmetric.c +3 -9
  76. data/vendor/NTRUplus/NTRU+768/symmetric.h +13 -3
  77. data/vendor/NTRUplus/NTRU+768/util.h +15 -0
  78. data/vendor/NTRUplus/NTRU+864/api.h +27 -8
  79. data/vendor/NTRUplus/NTRU+864/fips202/fips202.c +12 -269
  80. data/vendor/NTRUplus/NTRU+864/fips202/fips202.h +4 -113
  81. data/vendor/NTRUplus/NTRU+864/kem.c +110 -40
  82. data/vendor/NTRUplus/NTRU+864/ntt.c +24 -28
  83. data/vendor/NTRUplus/NTRU+864/poly.c +26 -12
  84. data/vendor/NTRUplus/NTRU+864/poly.h +3 -3
  85. data/vendor/NTRUplus/NTRU+864/randombytes.h +1 -0
  86. data/vendor/NTRUplus/NTRU+864/symmetric.c +3 -9
  87. data/vendor/NTRUplus/NTRU+864/symmetric.h +13 -3
  88. data/vendor/NTRUplus/NTRU+864/util.h +15 -0
  89. data/vendor/SMAUG-T/src/cbd.c +4 -4
  90. data/vendor/SMAUG-T/src/ciphertext.c +2 -2
  91. data/vendor/SMAUG-T/src/dg.c +2 -2
  92. data/vendor/SMAUG-T/src/hwt.c +4 -4
  93. data/vendor/SMAUG-T/src/indcpa.c +5 -5
  94. data/vendor/SMAUG-T/src/kem.c +9 -7
  95. data/vendor/SMAUG-T/src/key.c +2 -2
  96. data/vendor/SMAUG-T/src/pack.c +8 -8
  97. metadata +17 -42
  98. data/vendor/AIMer/aim2.c +0 -163
  99. data/vendor/AIMer/aim2.h +0 -36
  100. data/vendor/AIMer/aim2_constant.h +0 -74
  101. data/vendor/SOURCES.json +0 -130
@@ -1,4 +1,4 @@
1
- /* kpqc-py: propagate OS entropy failures (2026-09-06). */
1
+ #include "util.h"
2
2
  #include <stddef.h>
3
3
  #include <stdint.h>
4
4
  #include "api.h"
@@ -8,6 +8,13 @@
8
8
  #include "fips202/fips202.h"
9
9
  #include "randombytes.h"
10
10
 
11
+ #ifdef NTRUPLUS_SUPERCOP
12
+ #include "crypto_declassify.h"
13
+ #define ntruplus_declassify crypto_declassify
14
+ #else
15
+ #define ntruplus_declassify(x, xlen) ((void)(x), (void)(xlen))
16
+ #endif
17
+
11
18
  /*************************************************
12
19
  * Name: verify
13
20
  *
@@ -38,18 +45,19 @@ static inline int verify(const uint8_t *a, const uint8_t *b, size_t len)
38
45
  * Arguments: - poly *f: output polynomial f (NTT domain)
39
46
  * - poly *finv: output multiplicative inverse of f
40
47
  * in the NTT domain
48
+ * - uint8_t *buf: workspace of NTRUPLUS_N/4 bytes
41
49
  * - const uint8_t *coins: 32-byte deterministic seed
42
50
  *
43
51
  * Returns 0 on success; non-zero if f is not invertible in the NTT domain.
44
52
  **************************************************/
45
- static inline int genf_derand(poly *f, poly *finv, const uint8_t *coins)
53
+ static inline int genf_derand(poly *f, poly *finv,
54
+ uint8_t buf[NTRUPLUS_N / 4],
55
+ const uint8_t *coins)
46
56
  {
47
- uint8_t buf[NTRUPLUS_N / 4];
48
-
49
- shake256(buf, sizeof buf, coins, 32);
57
+ shake256(buf, NTRUPLUS_N / 4, coins, 32);
50
58
 
51
59
  poly_cbd1(f, buf);
52
- poly_triple(f, f);
60
+ poly_triple(f);
53
61
  f->coeffs[0] += 1;
54
62
 
55
63
  poly_ntt(f);
@@ -66,18 +74,19 @@ static inline int genf_derand(poly *f, poly *finv, const uint8_t *coins)
66
74
  * Arguments: - poly *g: output polynomial g (NTT domain)
67
75
  * - poly *ginv: output multiplicative inverse of g
68
76
  * in the NTT domain
77
+ * - uint8_t *buf: workspace of NTRUPLUS_N/4 bytes
69
78
  * - const uint8_t *coins: 32-byte deterministic seed
70
79
  *
71
80
  * Returns 0 on success; non-zero if g is not invertible in the NTT domain.
72
81
  **************************************************/
73
- static inline int geng_derand(poly *g, poly *ginv, const uint8_t *coins)
82
+ static inline int geng_derand(poly *g, poly *ginv,
83
+ uint8_t buf[NTRUPLUS_N / 4],
84
+ const uint8_t *coins)
74
85
  {
75
- uint8_t buf[NTRUPLUS_N / 4];
76
-
77
- shake256(buf, sizeof buf, coins, 32);
86
+ shake256(buf, NTRUPLUS_N / 4, coins, 32);
78
87
 
79
88
  poly_cbd1(g, buf);
80
- poly_triple(g, g);
89
+ poly_triple(g);
81
90
 
82
91
  poly_ntt(g);
83
92
 
@@ -113,6 +122,9 @@ static inline void crypto_kem_keypair_derand(uint8_t *pk, uint8_t *sk,
113
122
  poly_tobytes(sk, f);
114
123
  poly_tobytes(sk + NTRUPLUS_POLYBYTES, &hinv);
115
124
  hash_f(sk + 2 * NTRUPLUS_POLYBYTES, pk);
125
+
126
+ secure_clear(&h, sizeof h);
127
+ secure_clear(&hinv, sizeof hinv);
116
128
  }
117
129
 
118
130
  /*************************************************
@@ -130,23 +142,39 @@ static inline void crypto_kem_keypair_derand(uint8_t *pk, uint8_t *sk,
130
142
  *
131
143
  * Returns 0 on success.
132
144
  **************************************************/
133
- int crypto_kem_keypair(uint8_t *pk, uint8_t *sk)
145
+ int crypto_kem_keypair(unsigned char *pk, unsigned char *sk)
134
146
  {
135
147
  uint8_t coins[NTRUPLUS_SYMBYTES];
148
+ uint8_t buf[NTRUPLUS_N / 4];
149
+ int r;
150
+ int status = -1;
136
151
 
137
152
  poly f, finv;
138
153
  poly g, ginv;
139
154
 
140
155
  do {
141
- if (randombytes(coins, sizeof coins) != 0) return -1;
142
- } while (genf_derand(&f, &finv, coins));
156
+ if (randombytes(coins, sizeof coins) != 0) goto cleanup;
157
+ r = genf_derand(&f, &finv, buf, coins);
158
+ ntruplus_declassify(&r, sizeof r);
159
+ } while (r);
143
160
 
144
161
  do {
145
- if (randombytes(coins, sizeof coins) != 0) return -1;
146
- } while (geng_derand(&g, &ginv, coins));
162
+ if (randombytes(coins, sizeof coins) != 0) goto cleanup;
163
+ r = geng_derand(&g, &ginv, buf, coins);
164
+ ntruplus_declassify(&r, sizeof r);
165
+ } while (r);
147
166
 
148
167
  crypto_kem_keypair_derand(pk, sk, &f, &finv, &g, &ginv);
149
- return 0;
168
+ status = 0;
169
+
170
+ cleanup:
171
+ secure_clear(coins, sizeof coins);
172
+ secure_clear(buf, sizeof buf);
173
+ secure_clear(&f, sizeof f);
174
+ secure_clear(&finv, sizeof finv);
175
+ secure_clear(&g, sizeof g);
176
+ secure_clear(&ginv, sizeof ginv);
177
+ return status;
150
178
  }
151
179
 
152
180
  /*************************************************
@@ -162,17 +190,27 @@ int crypto_kem_keypair(uint8_t *pk, uint8_t *sk)
162
190
  * - const uint8_t *coins: input randomness for
163
191
  * deterministic encapsulation
164
192
  *
165
- * Returns 0 on success.
193
+ * Returns 0 on success. If pk contains a non-canonical coefficient, ct and ss
194
+ * are set to all zero bytes and 1 is returned.
166
195
  **************************************************/
167
196
  static inline int crypto_kem_enc_derand(uint8_t *ct, uint8_t *ss,
168
197
  const uint8_t *pk,
169
198
  const uint8_t *coins)
170
199
  {
171
- uint8_t msg[NTRUPLUS_N / 8 + NTRUPLUS_SYMBYTES];
172
- uint8_t buf1[NTRUPLUS_SYMBYTES + NTRUPLUS_N / 4];
173
- uint8_t buf2[NTRUPLUS_POLYBYTES];
200
+ uint8_t msg[HASH_H_INBYTES];
201
+ uint8_t buf1[HASH_H_OUTBYTES];
202
+ uint8_t buf2[HASH_G_INBYTES];
174
203
 
175
204
  poly c, h, r, m;
205
+
206
+ if(poly_frombytes(&h, pk))
207
+ {
208
+ for (size_t i = 0; i < NTRUPLUS_CIPHERTEXTBYTES; i++)
209
+ ct[i] = 0;
210
+ secure_clear(ss, NTRUPLUS_SSBYTES);
211
+
212
+ return 1;
213
+ }
176
214
 
177
215
  for (size_t i = 0; i < NTRUPLUS_N / 8; i++)
178
216
  msg[i] = coins[i];
@@ -188,12 +226,17 @@ static inline int crypto_kem_enc_derand(uint8_t *ct, uint8_t *ss,
188
226
  poly_sotp_encode(&m, msg, buf2);
189
227
  poly_ntt(&m);
190
228
 
191
- poly_frombytes(&h, pk);
192
229
  poly_basemul_add(&c, &h, &r, &m);
193
230
  poly_tobytes(ct, &c);
194
231
 
195
232
  for (size_t i = 0; i < NTRUPLUS_SSBYTES; i++)
196
233
  ss[i] = buf1[i];
234
+
235
+ secure_clear(msg, sizeof msg);
236
+ secure_clear(buf1, sizeof buf1);
237
+ secure_clear(buf2, sizeof buf2);
238
+ secure_clear(&r, sizeof r);
239
+ secure_clear(&m, sizeof m);
197
240
 
198
241
  return 0;
199
242
  }
@@ -212,14 +255,22 @@ static inline int crypto_kem_enc_derand(uint8_t *ct, uint8_t *ss,
212
255
  * - const uint8_t *pk: input public key
213
256
  * (array of CRYPTO_PUBLICKEYBYTES bytes)
214
257
  *
215
- * Returns 0 on success.
258
+ * Returns 0 on success. If pk contains a non-canonical coefficient, ct and ss
259
+ * are set to all zero bytes and 1 is returned.
216
260
  **************************************************/
217
- int crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk)
261
+ int crypto_kem_enc(unsigned char *ct, unsigned char *ss,
262
+ const unsigned char *pk)
218
263
  {
219
264
  uint8_t coins[NTRUPLUS_N / 8];
265
+ int ret;
220
266
 
221
- if (randombytes(coins, sizeof coins) != 0) return -1;
222
- return crypto_kem_enc_derand(ct, ss, pk, coins);
267
+ if (randombytes(coins, sizeof coins) != 0) {
268
+ secure_clear(coins, sizeof coins);
269
+ return -1;
270
+ }
271
+ ret = crypto_kem_enc_derand(ct, ss, pk, coins);
272
+ secure_clear(coins, sizeof coins);
273
+ return ret;
223
274
  }
224
275
 
225
276
  /*************************************************
@@ -238,26 +289,32 @@ int crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk)
238
289
  *
239
290
  * Returns 0 on success, 1 on failure.
240
291
  **************************************************/
241
- int crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk)
292
+ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct,
293
+ const unsigned char *sk)
242
294
  {
243
- uint8_t msg[NTRUPLUS_N / 8 + NTRUPLUS_SYMBYTES];
244
- uint8_t buf1[NTRUPLUS_POLYBYTES];
245
- uint8_t buf2[NTRUPLUS_POLYBYTES];
246
- uint8_t buf3[NTRUPLUS_POLYBYTES + NTRUPLUS_SYMBYTES];
247
-
248
- int8_t fail;
295
+ uint8_t msg[HASH_H_INBYTES];
296
+ uint8_t buf1[HASH_G_INBYTES];
297
+ uint8_t buf2[HASH_G_INBYTES];
298
+ uint8_t buf3[HASH_H_OUTBYTES];
299
+
300
+ int8_t fail = 1;
249
301
 
250
302
  poly c, f, hinv;
251
303
  poly r1, r2;
252
304
  poly m1, m2;
253
-
254
- poly_frombytes(&c, ct);
255
- poly_frombytes(&f, sk);
256
- poly_frombytes(&hinv, sk + NTRUPLUS_POLYBYTES);
305
+
306
+ if(poly_frombytes(&c, ct) ||
307
+ poly_frombytes(&f, sk) ||
308
+ poly_frombytes(&hinv, sk + NTRUPLUS_POLYBYTES))
309
+ {
310
+ secure_clear(ss, NTRUPLUS_SSBYTES);
311
+
312
+ goto cleanup;
313
+ }
257
314
 
258
315
  poly_basemul(&m1, &c, &f);
259
316
  poly_invntt(&m1);
260
- poly_crepmod3(&m1, &m1);
317
+ poly_crepmod3(&m1);
261
318
 
262
319
  m2 = m1;
263
320
  poly_ntt(&m2);
@@ -268,7 +325,7 @@ int crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk)
268
325
  hash_g(buf2, buf1);
269
326
  fail = poly_sotp_decode(msg, &m1, buf2);
270
327
 
271
- for (size_t i = 0; i < NTRUPLUS_SYMBYTES; i++)
328
+ for (size_t i = 0; i < HASH_F_OUTBYTES; i++)
272
329
  msg[i + NTRUPLUS_N / 8] = sk[i + 2 * NTRUPLUS_POLYBYTES];
273
330
 
274
331
  hash_h(buf3, msg);
@@ -281,6 +338,19 @@ int crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk)
281
338
 
282
339
  for (size_t i = 0; i < NTRUPLUS_SSBYTES; i++)
283
340
  ss[i] = buf3[i] & ~(-fail);
284
-
341
+
342
+ cleanup:
343
+ secure_clear(msg, sizeof msg);
344
+ secure_clear(buf1, sizeof buf1);
345
+ secure_clear(buf2, sizeof buf2);
346
+ secure_clear(buf3, sizeof buf3);
347
+ secure_clear(&c, sizeof c);
348
+ secure_clear(&f, sizeof f);
349
+ secure_clear(&hinv, sizeof hinv);
350
+ secure_clear(&r1, sizeof r1);
351
+ secure_clear(&r2, sizeof r2);
352
+ secure_clear(&m1, sizeof m1);
353
+ secure_clear(&m2, sizeof m2);
354
+
285
355
  return fail;
286
356
  }
@@ -115,8 +115,9 @@ static inline int16_t fqmul(int16_t a, int16_t b)
115
115
  /*************************************************
116
116
  * Name: fqinv
117
117
  *
118
- * Description: Computes the multiplicative inverse of a value in the
119
- * finite field Z_q.
118
+ * Description: Computes the multiplicative inverse in Z_q using Fermat's
119
+ * little theorem. The exponent q-2 = 3455 is evaluated using
120
+ * a shortest addition chain of length 15 (OEIS A003313).
120
121
  *
121
122
  * Arguments: - int16_t a: input value a mod q
122
123
  *
@@ -124,32 +125,27 @@ static inline int16_t fqmul(int16_t a, int16_t b)
124
125
  **************************************************/
125
126
  static inline int16_t fqinv(int16_t a)
126
127
  {
127
- int16_t t1, t2, t3;
128
-
129
- t1 = fqmul(a, a); // 10
130
- t2 = fqmul(t1, t1); // 100
131
- t2 = fqmul(t2, t2); // 1000
132
- t3 = fqmul(t2, t2); // 10000
133
-
134
- t1 = fqmul(t1, t2); // 1010
135
-
136
- t2 = fqmul(t1, t3); // 11010
137
- t2 = fqmul(t2, t2); // 110100
138
- t2 = fqmul(t2, a); // 110101
139
-
140
- t1 = fqmul(t1, t2); // 111111
141
-
142
- t2 = fqmul(t2, t2); // 1101010
143
- t2 = fqmul(t2, t2); // 11010100
144
- t2 = fqmul(t2, t2); // 110101000
145
- t2 = fqmul(t2, t2); // 1101010000
146
- t2 = fqmul(t2, t2); // 11010100000
147
- t2 = fqmul(t2, t2); // 110101000000
148
- t2 = fqmul(t2, t1); // 110101111111
149
-
150
- t2 = fqmul(NTRUPLUS_RINV, t2);
151
-
152
- return t2;
128
+ int16_t t0, t1;
129
+
130
+ t0 = fqmul(a, a); // 10
131
+ t0 = fqmul(t0, t0); // 100
132
+ t0 = fqmul(t0, t0); // 1000
133
+ t0 = fqmul(t0, t0); // 10000
134
+ t1 = fqmul(t0, a); // 10001
135
+
136
+ t0 = fqmul(t0, t0); // 100000
137
+ t0 = fqmul(t0, t0); // 1000000
138
+ t0 = fqmul(t0, t0); // 10000000
139
+ t1 = fqmul(t0, t1); // 10010001
140
+
141
+ t0 = fqmul(t1, t0); // 100010001
142
+ t1 = fqmul(t0, t1); // 110100010
143
+ t1 = fqmul(t1, t0); // 1010110011
144
+ t0 = fqmul(t1, t1); // 10101100110
145
+ t0 = fqmul(t0, t0); // 101011001100
146
+ t0 = fqmul(t0, t1); // 110101111111
147
+
148
+ return fqmul(NTRUPLUS_RINV, t0);
153
149
  }
154
150
 
155
151
  /*************************************************
@@ -42,7 +42,6 @@ void poly_tobytes(uint8_t r[NTRUPLUS_POLYBYTES], const poly *a)
42
42
  {
43
43
  int16_t t[2];
44
44
 
45
- #pragma GCC unroll 2
46
45
  for(size_t i = 0; i < NTRUPLUS_N/2; i++)
47
46
  {
48
47
  t[0] = a->coeffs[2*i];
@@ -65,14 +64,25 @@ void poly_tobytes(uint8_t r[NTRUPLUS_POLYBYTES], const poly *a)
65
64
  * Arguments: - poly *r: pointer to output polynomial
66
65
  * - const uint8_t *a: pointer to input byte array
67
66
  * (of NTRUPLUS_POLYBYTES bytes)
67
+ *
68
+ * Returns 0 on success, 1 if any coefficient is greater than or equal to q.
68
69
  **************************************************/
69
- void poly_frombytes(poly *r, const uint8_t a[NTRUPLUS_POLYBYTES])
70
+ int poly_frombytes(poly *r, const uint8_t a[NTRUPLUS_POLYBYTES])
70
71
  {
72
+ uint32_t fail = 0;
73
+
71
74
  for(size_t i = 0; i < NTRUPLUS_N/2; i++)
72
75
  {
73
- r->coeffs[2*i] = ((a[3*i+0] >> 0) | ((uint16_t)a[3*i+1] << 8)) & 0xFFF;
74
- r->coeffs[2*i+1] = ((a[3*i+1] >> 4) | ((uint16_t)a[3*i+2] << 4)) & 0xFFF;
76
+ const uint16_t t0 = ((a[3*i+0] >> 0) | ((uint16_t)a[3*i+1] << 8)) & 0xFFF;
77
+ const uint16_t t1 = ((a[3*i+1] >> 4) | ((uint16_t)a[3*i+2] << 4)) & 0xFFF;
78
+
79
+ r->coeffs[2*i] = t0;
80
+ r->coeffs[2*i+1] = t1;
81
+ fail |= (uint32_t)(NTRUPLUS_Q - 1) - t0;
82
+ fail |= (uint32_t)(NTRUPLUS_Q - 1) - t1;
75
83
  }
84
+
85
+ return fail >> 31;
76
86
  }
77
87
 
78
88
  /*************************************************
@@ -147,6 +157,7 @@ int poly_sotp_decode(uint8_t msg[NTRUPLUS_N/8], const poly *a, const uint8_t buf
147
157
  uint8_t t1, t2, t3;
148
158
  uint16_t t4;
149
159
  uint32_t r = 0;
160
+ volatile uint8_t mask;
150
161
 
151
162
  for(size_t i = 0; i < NTRUPLUS_N / 8; i++)
152
163
  {
@@ -172,6 +183,11 @@ int poly_sotp_decode(uint8_t msg[NTRUPLUS_N/8], const poly *a, const uint8_t buf
172
183
  r = r >> 1;
173
184
  r = (-(uint32_t)r) >> 31;
174
185
 
186
+ mask = (uint8_t)(r - 1);
187
+
188
+ for (size_t i = 0; i < NTRUPLUS_N / 8; i++)
189
+ msg[i] &= mask;
190
+
175
191
  return r;
176
192
  }
177
193
 
@@ -290,13 +306,12 @@ void poly_sub(poly *r, const poly *a, const poly *b)
290
306
  *
291
307
  * Description: Multiply polynomial by 3; no modular reduction is performed
292
308
  *
293
- * Arguments: - poly *r: pointer to output polynomial
294
- * - const poly *a: pointer to input polynomial
309
+ * Arguments: - poly *r: pointer to input/output polynomial
295
310
  **************************************************/
296
- void poly_triple(poly *r, const poly *a)
311
+ void poly_triple(poly *r)
297
312
  {
298
313
  for(int i = 0; i < NTRUPLUS_N; ++i)
299
- r->coeffs[i] = 3*a->coeffs[i];
314
+ r->coeffs[i] *= 3;
300
315
  }
301
316
 
302
317
  /*************************************************
@@ -304,11 +319,10 @@ void poly_triple(poly *r, const poly *a)
304
319
  *
305
320
  * Description: Compute modulus 3 operation to polynomial
306
321
  *
307
- * Arguments: - poly *r: pointer to output polynomial
308
- * - const poly *a: pointer to input polynomial
322
+ * Arguments: - poly *r: pointer to input/output polynomial
309
323
  **************************************************/
310
- void poly_crepmod3(poly *r, const poly *a)
324
+ void poly_crepmod3(poly *r)
311
325
  {
312
326
  for(int i = 0; i < NTRUPLUS_N; i++)
313
- r->coeffs[i] = crepmod3(a->coeffs[i]);
327
+ r->coeffs[i] = crepmod3(r->coeffs[i]);
314
328
  }
@@ -13,7 +13,7 @@ typedef struct{
13
13
  } poly;
14
14
 
15
15
  void poly_tobytes(uint8_t r[NTRUPLUS_POLYBYTES], const poly *a);
16
- void poly_frombytes(poly *r, const uint8_t a[NTRUPLUS_POLYBYTES]);
16
+ int poly_frombytes(poly *r, const uint8_t a[NTRUPLUS_POLYBYTES]);
17
17
 
18
18
  void poly_cbd1(poly *r, const uint8_t buf[NTRUPLUS_N/4]);
19
19
  void poly_sotp_encode(poly *r, const uint8_t msg[NTRUPLUS_N/8], const uint8_t buf[NTRUPLUS_N/4]);
@@ -25,7 +25,7 @@ int poly_baseinv(poly *r, const poly *a);
25
25
  void poly_basemul(poly *r, const poly *a, const poly *b);
26
26
  void poly_basemul_add(poly *r, const poly *a, const poly *b, const poly *c);
27
27
  void poly_sub(poly *r, const poly *a, const poly *b);
28
- void poly_triple(poly *r, const poly *a);
29
- void poly_crepmod3(poly *r, const poly *a);
28
+ void poly_triple(poly *r);
29
+ void poly_crepmod3(poly *r);
30
30
 
31
31
  #endif
@@ -4,6 +4,7 @@
4
4
  #include <stddef.h>
5
5
  #include <stdint.h>
6
6
 
7
+ /* KpqC bindings propagate failures from the operating-system entropy source. */
7
8
  int randombytes(uint8_t *out, size_t outlen);
8
9
 
9
10
  #endif
@@ -1,16 +1,8 @@
1
+ #include "util.h"
1
2
  #include <string.h>
2
3
  #include "symmetric.h"
3
4
  #include "fips202/fips202.h"
4
5
 
5
- #define HASH_F_INBYTES (NTRUPLUS_POLYBYTES)
6
- #define HASH_F_OUTBYTES (32)
7
-
8
- #define HASH_G_INBYTES (NTRUPLUS_POLYBYTES)
9
- #define HASH_G_OUTBYTES (NTRUPLUS_N / 4)
10
-
11
- #define HASH_H_INBYTES (NTRUPLUS_N / 8 + NTRUPLUS_SYMBYTES)
12
- #define HASH_H_OUTBYTES (NTRUPLUS_SSBYTES + NTRUPLUS_N / 4)
13
-
14
6
  void hash_f(uint8_t *buf, const uint8_t *msg)
15
7
  {
16
8
  uint8_t data[1 + HASH_F_INBYTES];
@@ -27,6 +19,7 @@ void hash_g(uint8_t *buf, const uint8_t *msg)
27
19
  data[0] = 0x01;
28
20
  memcpy(data + 1, msg, HASH_G_INBYTES);
29
21
  shake256(buf, HASH_G_OUTBYTES, data, HASH_G_INBYTES + 1);
22
+ secure_clear(data, sizeof data);
30
23
  }
31
24
 
32
25
  void hash_h(uint8_t *buf, const uint8_t *msg)
@@ -36,4 +29,5 @@ void hash_h(uint8_t *buf, const uint8_t *msg)
36
29
  data[0] = 0x02;
37
30
  memcpy(data + 1, msg, HASH_H_INBYTES);
38
31
  shake256(buf, HASH_H_OUTBYTES, data, HASH_H_INBYTES + 1);
32
+ secure_clear(data, sizeof data);
39
33
  }
@@ -3,10 +3,20 @@
3
3
 
4
4
  #include <stddef.h>
5
5
  #include <stdint.h>
6
+ #include "api.h"
6
7
  #include "params.h"
7
8
 
8
- void hash_f(uint8_t *buf, const uint8_t *msg);
9
- void hash_g(uint8_t *buf, const uint8_t *msg);
10
- void hash_h(uint8_t *buf, const uint8_t *msg);
9
+ #define HASH_F_INBYTES (NTRUPLUS_POLYBYTES)
10
+ #define HASH_F_OUTBYTES (NTRUPLUS_SYMBYTES)
11
+
12
+ #define HASH_G_INBYTES (NTRUPLUS_POLYBYTES)
13
+ #define HASH_G_OUTBYTES (NTRUPLUS_N / 4)
14
+
15
+ #define HASH_H_INBYTES (NTRUPLUS_N / 8 + NTRUPLUS_SYMBYTES)
16
+ #define HASH_H_OUTBYTES (NTRUPLUS_SSBYTES + NTRUPLUS_N / 4)
17
+
18
+ NTRUPLUS_INTERNAL void hash_f(uint8_t *buf, const uint8_t *msg);
19
+ NTRUPLUS_INTERNAL void hash_g(uint8_t *buf, const uint8_t *msg);
20
+ NTRUPLUS_INTERNAL void hash_h(uint8_t *buf, const uint8_t *msg);
11
21
 
12
22
  #endif /* SYMMETRIC_H */
@@ -0,0 +1,15 @@
1
+ #ifndef NTRUPLUS_UTIL_H
2
+ #define NTRUPLUS_UTIL_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ static inline void secure_clear(void *v, size_t len)
8
+ {
9
+ volatile uint8_t *p = v;
10
+
11
+ while (len-- > 0)
12
+ *p++ = 0;
13
+ }
14
+
15
+ #endif /* NTRUPLUS_UTIL_H */
@@ -24,7 +24,7 @@ static uint32_t load24_littleendian(const uint8_t x[3]) {
24
24
  * - const uint8_t buf[SMAUGT_CBDSEED_BYTES]: pointer to input byte
25
25
  * array
26
26
  *
27
- * Specification: Implements Algorithm 7, spCBD1.
27
+ * Specification: Implements @[KS X 123456, Algorithm 7, spCBD1]
28
28
  **************************************************/
29
29
  #define sp_cbd1 SMAUGT_NAMESPACE(sp_cbd1)
30
30
  static void sp_cbd1(poly *r, const uint8_t buf[SMAUGT_CBDSEED_BYTES]) {
@@ -81,7 +81,7 @@ static uint32_t load32_littleendian(const uint8_t x[4]) {
81
81
  * - const uint8_t buf[SMAUGT_CBDSEED_BYTES]: pointer to input byte
82
82
  * array
83
83
  *
84
- * Specification: Implements Algorithm 9, CBD.
84
+ * Specification: Implements @[KS X 123456, Algorithm 9, CBD]
85
85
  **************************************************/
86
86
  #define cbd SMAUGT_NAMESPACE(cbd)
87
87
  static void cbd(poly *r, const uint8_t buf[SMAUGT_CBDSEED_BYTES]) {
@@ -113,7 +113,7 @@ static void cbd(poly *r, const uint8_t buf[SMAUGT_CBDSEED_BYTES]) {
113
113
  * - const uint8_t buf[SMAUGT_CBDSEED_BYTES]: pointer to input byte
114
114
  * array
115
115
  *
116
- * Specification: Implements Algorithm 8, spCBD2.
116
+ * Specification: Implements @[KS X 123456, Algorithm 8, spCBD2]
117
117
  **************************************************/
118
118
  #define sp_cbd2 SMAUGT_NAMESPACE(sp_cbd2)
119
119
  static void sp_cbd2(poly *r, const uint8_t buf[SMAUGT_CBDSEED_BYTES]) {
@@ -146,7 +146,7 @@ static void sp_cbd2(poly *r, const uint8_t buf[SMAUGT_CBDSEED_BYTES]) {
146
146
  * - const uint8_t buf[SMAUGT_CBDSEED_BYTES]: pointer to input byte
147
147
  * array
148
148
  *
149
- * Specification: Implements Algorithm 6, spCBD.
149
+ * Specification: Implements @[KS X 123456, Algorithm 6, spCBD]
150
150
  **************************************************/
151
151
  void sp_cbd(poly *r, const uint8_t buf[SMAUGT_CBDSEED_BYTES]) {
152
152
  #if SMAUGT_MODE == SMAUGT_MODE1 || SMAUGT_MODE == SMAUGT_MODET
@@ -10,7 +10,7 @@
10
10
  * Arguments: - polyvec *a: pointer to inout vector a. This should be
11
11
  * already initialized.
12
12
  *
13
- * Specification: Implements Algorithm 12, Round1.
13
+ * Specification: Implements @[KS X 123456, Algorithm 12, Round1]
14
14
  **************************************************/
15
15
  #define round1 SMAUGT_NAMESPACE(round1)
16
16
  static inline void round1(polyvec *a) {
@@ -50,7 +50,7 @@ void computeC1(polyvec *c1, const polyvec A[SMAUGT_K], const polyvec *r) {
50
50
  * Arguments: - poly *a: pointer to an input/output vector a. This should be
51
51
  * already initialized.
52
52
  *
53
- * Specification: Implements Algorithm 13, Round2.
53
+ * Specification: Implements @[KS X 123456, Algorithm 13, Round2]
54
54
  **************************************************/
55
55
  #define round2 SMAUGT_NAMESPACE(round2)
56
56
  static inline void round2(poly *a) {
@@ -53,7 +53,7 @@ static void load64_littleendian(uint64_t *out, size_t outlen,
53
53
  * - const uint8_t *seed: pointer to input seed (of length
54
54
  * SMAUGT_CRYPTO_BYTES+1)
55
55
  *
56
- * Specification: Implements Algorithm 11, dGaussianPoly.
56
+ * Specification: Implements @[KS X 123456, Algorithm 11, dGaussianPoly]
57
57
  **************************************************/
58
58
  int d_gaussian_poly(poly *op, const uint8_t *seed) {
59
59
  unsigned int i = 0, j = 0, k = 0;
@@ -99,7 +99,7 @@ int d_gaussian_poly(poly *op, const uint8_t *seed) {
99
99
  * - const uint8_t seed[SMAUGT_CRYPTO_BYTES]: pointer to input byte
100
100
  * array
101
101
  *
102
- * Specification: Implements Algorithm 10, dGaussian.
102
+ * Specification: Implements @[KS X 123456, Algorithm 10, dGaussian]
103
103
  **************************************************/
104
104
  void d_gaussian(polyvec *op, const uint8_t seed[SMAUGT_CRYPTO_BYTES]) {
105
105
  unsigned int i;
@@ -16,8 +16,8 @@
16
16
  #define load16_littleendian SMAUGT_NAMESPACE(load16_littleendian)
17
17
  static void load16_littleendian(uint16_t *out, size_t outlen,
18
18
  const uint8_t *in) {
19
- size_t pos = 0;
20
- for (size_t i = 0; i < outlen; ++i) {
19
+ int pos = 0;
20
+ for (int i = 0; i < outlen; ++i) {
21
21
  out[i] = ((uint16_t)(in[pos])) | ((uint16_t)(in[pos + 1]) << 8);
22
22
  pos += 2;
23
23
  }
@@ -39,7 +39,7 @@ static void load16_littleendian(uint16_t *out, size_t outlen,
39
39
  * - const uint16_t *seed: pointer to input seed (of length
40
40
  * SMAUGT_HWTSEEDBYTES/2)
41
41
  *
42
- * Specification: Implements Algorithm 4, RejSampleMod.
42
+ * Specification: Implements @[KS X 123456, Algorithm 4, RejSampleMod]
43
43
  **************************************************/
44
44
  #define rej_sample_mod SMAUGT_NAMESPACE(rej_sample_mod)
45
45
  static int rej_sample_mod(int16_t si[SMAUGT_N], const uint16_t *rand) {
@@ -79,7 +79,7 @@ static int rej_sample_mod(int16_t si[SMAUGT_N], const uint16_t *rand) {
79
79
  * - const uint8_t *seed: pointer to input seed (of length
80
80
  * SMAUGT_CRYPTO_BYTES + 2)
81
81
  *
82
- * Specification: Implements Algorithm 3, HWT.
82
+ * Specification: Implements @[KS X 123456, Algorithm 3, HWT]
83
83
  **************************************************/
84
84
  int hwt(int16_t *res, const uint8_t *seed) {
85
85
  unsigned int i;