pq_crypto 0.3.2 → 0.4.2

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +56 -0
  3. data/CHANGELOG.md +37 -0
  4. data/GET_STARTED.md +361 -40
  5. data/README.md +58 -241
  6. data/SECURITY.md +101 -82
  7. data/ext/pqcrypto/extconf.rb +40 -7
  8. data/ext/pqcrypto/mldsa_api.h +71 -1
  9. data/ext/pqcrypto/mlkem_api.h +24 -0
  10. data/ext/pqcrypto/pq_externalmu.c +14 -1
  11. data/ext/pqcrypto/pqcrypto_ruby_secure.c +484 -81
  12. data/ext/pqcrypto/pqcrypto_secure.c +179 -72
  13. data/ext/pqcrypto/pqcrypto_secure.h +87 -7
  14. data/ext/pqcrypto/pqcrypto_version.h +7 -0
  15. data/ext/pqcrypto/vendor/.vendored +1 -1
  16. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/LICENSE +5 -0
  17. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/Makefile +19 -0
  18. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/Makefile.Microsoft_nmake +23 -0
  19. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/api.h +18 -0
  20. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/cbd.c +83 -0
  21. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/cbd.h +11 -0
  22. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/indcpa.c +327 -0
  23. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/indcpa.h +22 -0
  24. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/kem.c +164 -0
  25. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/kem.h +23 -0
  26. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/ntt.c +146 -0
  27. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/ntt.h +14 -0
  28. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/params.h +36 -0
  29. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/poly.c +311 -0
  30. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/poly.h +37 -0
  31. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/polyvec.c +198 -0
  32. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/polyvec.h +26 -0
  33. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/reduce.c +41 -0
  34. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/reduce.h +13 -0
  35. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/symmetric-shake.c +71 -0
  36. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/symmetric.h +30 -0
  37. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/verify.c +67 -0
  38. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/verify.h +13 -0
  39. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/LICENSE +5 -0
  40. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/Makefile +19 -0
  41. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/Makefile.Microsoft_nmake +23 -0
  42. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/api.h +18 -0
  43. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/cbd.c +108 -0
  44. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/cbd.h +11 -0
  45. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/indcpa.c +327 -0
  46. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/indcpa.h +22 -0
  47. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/kem.c +164 -0
  48. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/kem.h +23 -0
  49. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/ntt.c +146 -0
  50. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/ntt.h +14 -0
  51. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/params.h +36 -0
  52. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/poly.c +299 -0
  53. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/poly.h +37 -0
  54. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/polyvec.c +188 -0
  55. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/polyvec.h +26 -0
  56. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/reduce.c +41 -0
  57. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/reduce.h +13 -0
  58. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/symmetric-shake.c +71 -0
  59. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/symmetric.h +30 -0
  60. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/verify.c +67 -0
  61. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/verify.h +13 -0
  62. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/LICENSE +5 -0
  63. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/Makefile +19 -0
  64. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/Makefile.Microsoft_nmake +23 -0
  65. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/api.h +50 -0
  66. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/ntt.c +98 -0
  67. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/ntt.h +10 -0
  68. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/packing.c +261 -0
  69. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/packing.h +31 -0
  70. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/params.h +44 -0
  71. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/poly.c +848 -0
  72. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/poly.h +52 -0
  73. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/polyvec.c +415 -0
  74. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/polyvec.h +65 -0
  75. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/reduce.c +69 -0
  76. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/reduce.h +17 -0
  77. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/rounding.c +98 -0
  78. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/rounding.h +14 -0
  79. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/sign.c +407 -0
  80. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/sign.h +47 -0
  81. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/symmetric-shake.c +26 -0
  82. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/symmetric.h +34 -0
  83. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/LICENSE +5 -0
  84. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/Makefile +19 -0
  85. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/Makefile.Microsoft_nmake +23 -0
  86. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/api.h +50 -0
  87. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/ntt.c +98 -0
  88. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/ntt.h +10 -0
  89. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/packing.c +261 -0
  90. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/packing.h +31 -0
  91. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/params.h +44 -0
  92. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/poly.c +823 -0
  93. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/poly.h +52 -0
  94. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/polyvec.c +415 -0
  95. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/polyvec.h +65 -0
  96. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/reduce.c +69 -0
  97. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/reduce.h +17 -0
  98. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/rounding.c +92 -0
  99. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/rounding.h +14 -0
  100. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/sign.c +407 -0
  101. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/sign.h +47 -0
  102. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/symmetric-shake.c +26 -0
  103. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/symmetric.h +34 -0
  104. data/lib/pq_crypto/algorithm_registry.rb +200 -0
  105. data/lib/pq_crypto/hybrid_kem.rb +1 -12
  106. data/lib/pq_crypto/kem.rb +104 -13
  107. data/lib/pq_crypto/pkcs8.rb +387 -0
  108. data/lib/pq_crypto/serialization.rb +1 -14
  109. data/lib/pq_crypto/signature.rb +123 -17
  110. data/lib/pq_crypto/spki.rb +131 -0
  111. data/lib/pq_crypto/version.rb +1 -1
  112. data/lib/pq_crypto.rb +78 -19
  113. data/script/vendor_libs.rb +4 -0
  114. metadata +95 -3
@@ -1,4 +1,5 @@
1
1
  #include "pqcrypto_secure.h"
2
+ #include "pqcrypto_version.h"
2
3
 
3
4
  #include <stdio.h>
4
5
  #include <sys/types.h>
@@ -49,15 +50,6 @@ static int pq_size_add(size_t a, size_t b, size_t *out) {
49
50
  return PQ_SUCCESS;
50
51
  }
51
52
 
52
- static int pq_size_mul(size_t a, size_t b, size_t *out) {
53
- if (!out)
54
- return PQ_ERROR_BUFFER;
55
- if (a != 0 && SIZE_MAX / a < b)
56
- return PQ_ERROR_BUFFER;
57
- *out = a * b;
58
- return PQ_SUCCESS;
59
- }
60
-
61
53
  static int pq_is_pem_whitespace(char c) {
62
54
  return c == '\n' || c == '\r' || c == ' ' || c == '\t';
63
55
  }
@@ -256,101 +248,216 @@ cleanup:
256
248
  return ret;
257
249
  }
258
250
 
259
- int pq_mlkem_keypair(uint8_t *pk, uint8_t *sk) {
260
- return PQCLEAN_MLKEM768_CLEAN_crypto_kem_keypair(pk, sk) == 0 ? PQ_SUCCESS : PQ_ERROR_KEYPAIR;
261
- }
251
+ #define PQ_MLKEM_VARIANTS(X) \
252
+ X(mlkem, MLKEM768_CLEAN) \
253
+ X(mlkem512, MLKEM512_CLEAN) \
254
+ X(mlkem1024, MLKEM1024_CLEAN)
255
+
256
+ #define PQ_DEFINE_MLKEM_SHIMS(prefix, pqclean) \
257
+ int pq_##prefix##_keypair(uint8_t *pk, uint8_t *sk) { \
258
+ return PQCLEAN_##pqclean##_crypto_kem_keypair(pk, sk) == 0 ? PQ_SUCCESS \
259
+ : PQ_ERROR_KEYPAIR; \
260
+ } \
261
+ int pq_##prefix##_keypair_from_seed(uint8_t *pk, uint8_t *sk, const uint8_t *seed64) { \
262
+ if (!pk || !sk || !seed64) { \
263
+ return PQ_ERROR_BUFFER; \
264
+ } \
265
+ return PQCLEAN_##pqclean##_crypto_kem_keypair_derand(pk, sk, seed64) == 0 \
266
+ ? PQ_SUCCESS \
267
+ : PQ_ERROR_KEYPAIR; \
268
+ } \
269
+ int pq_##prefix##_encapsulate(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { \
270
+ return PQCLEAN_##pqclean##_crypto_kem_enc(ct, ss, pk) == 0 ? PQ_SUCCESS \
271
+ : PQ_ERROR_ENCAPSULATE; \
272
+ } \
273
+ int pq_##prefix##_decapsulate(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { \
274
+ return PQCLEAN_##pqclean##_crypto_kem_dec(ss, ct, sk) == 0 ? PQ_SUCCESS \
275
+ : PQ_ERROR_DECAPSULATE; \
276
+ }
262
277
 
263
- int pq_mlkem_encapsulate(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
264
- return PQCLEAN_MLKEM768_CLEAN_crypto_kem_enc(ct, ss, pk) == 0 ? PQ_SUCCESS
265
- : PQ_ERROR_ENCAPSULATE;
266
- }
278
+ PQ_MLKEM_VARIANTS(PQ_DEFINE_MLKEM_SHIMS)
267
279
 
268
- int pq_mlkem_decapsulate(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
269
- return PQCLEAN_MLKEM768_CLEAN_crypto_kem_dec(ss, ct, sk) == 0 ? PQ_SUCCESS
270
- : PQ_ERROR_DECAPSULATE;
271
- }
280
+ #undef PQ_DEFINE_MLKEM_SHIMS
272
281
 
273
- int pq_testing_mlkem_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
274
- const uint8_t *seed, size_t seed_len) {
275
- if (!public_key || !secret_key || !seed || seed_len != 64) {
282
+ static int pq_testing_mlkem_keypair_from_seed_with(uint8_t *public_key, uint8_t *secret_key,
283
+ const uint8_t *seed, size_t seed_len,
284
+ int (*keypair_derand)(uint8_t *, uint8_t *,
285
+ const uint8_t *)) {
286
+ if (!public_key || !secret_key || !seed || seed_len != 64 || !keypair_derand) {
276
287
  return PQ_ERROR_BUFFER;
277
288
  }
278
- return PQCLEAN_MLKEM768_CLEAN_crypto_kem_keypair_derand(public_key, secret_key, seed) == 0
279
- ? PQ_SUCCESS
280
- : PQ_ERROR_KEYPAIR;
289
+ return keypair_derand(public_key, secret_key, seed) == 0 ? PQ_SUCCESS : PQ_ERROR_KEYPAIR;
281
290
  }
282
291
 
283
- int pq_testing_mlkem_encapsulate_from_seed(uint8_t *ciphertext, uint8_t *shared_secret,
284
- const uint8_t *public_key, const uint8_t *seed,
285
- size_t seed_len) {
286
- if (!ciphertext || !shared_secret || !public_key || !seed || seed_len != 32) {
292
+ static int pq_testing_mlkem_encapsulate_from_seed_with(
293
+ uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key, const uint8_t *seed,
294
+ size_t seed_len, int (*enc_derand)(uint8_t *, uint8_t *, const uint8_t *, const uint8_t *)) {
295
+ if (!ciphertext || !shared_secret || !public_key || !seed || seed_len != 32 || !enc_derand) {
287
296
  return PQ_ERROR_BUFFER;
288
297
  }
289
- return PQCLEAN_MLKEM768_CLEAN_crypto_kem_enc_derand(ciphertext, shared_secret, public_key,
290
- seed) == 0
291
- ? PQ_SUCCESS
292
- : PQ_ERROR_ENCAPSULATE;
298
+ return enc_derand(ciphertext, shared_secret, public_key, seed) == 0 ? PQ_SUCCESS
299
+ : PQ_ERROR_ENCAPSULATE;
293
300
  }
294
301
 
295
- int pq_sign_keypair(uint8_t *public_key, uint8_t *secret_key) {
296
- return PQCLEAN_MLDSA65_CLEAN_crypto_sign_keypair(public_key, secret_key) == 0
297
- ? PQ_SUCCESS
298
- : PQ_ERROR_KEYPAIR;
299
- }
302
+ #define PQ_DEFINE_MLKEM_TESTING_SHIMS(prefix, pqclean) \
303
+ int pq_testing_##prefix##_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key, \
304
+ const uint8_t *seed, size_t seed_len) { \
305
+ return pq_testing_mlkem_keypair_from_seed_with( \
306
+ public_key, secret_key, seed, seed_len, \
307
+ PQCLEAN_##pqclean##_crypto_kem_keypair_derand); \
308
+ } \
309
+ int pq_testing_##prefix##_encapsulate_from_seed(uint8_t *ciphertext, uint8_t *shared_secret, \
310
+ const uint8_t *public_key, \
311
+ const uint8_t *seed, size_t seed_len) { \
312
+ return pq_testing_mlkem_encapsulate_from_seed_with( \
313
+ ciphertext, shared_secret, public_key, seed, seed_len, \
314
+ PQCLEAN_##pqclean##_crypto_kem_enc_derand); \
315
+ }
300
316
 
301
- int pq_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len,
302
- const uint8_t *secret_key) {
303
- return PQCLEAN_MLDSA65_CLEAN_crypto_sign_signature(signature, signature_len, message,
304
- message_len, secret_key) == 0
305
- ? PQ_SUCCESS
306
- : PQ_ERROR_SIGN;
307
- }
317
+ PQ_MLKEM_VARIANTS(PQ_DEFINE_MLKEM_TESTING_SHIMS)
308
318
 
309
- int pq_verify(const uint8_t *signature, size_t signature_len, const uint8_t *message,
310
- size_t message_len, const uint8_t *public_key) {
311
- return PQCLEAN_MLDSA65_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len,
312
- public_key) == 0
313
- ? PQ_SUCCESS
314
- : PQ_ERROR_VERIFY;
315
- }
319
+ #undef PQ_DEFINE_MLKEM_TESTING_SHIMS
316
320
 
317
- int pq_testing_mldsa_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
318
- const uint8_t *seed, size_t seed_len) {
319
- int rc;
320
- if (!public_key || !secret_key || !seed) {
321
- return PQ_ERROR_BUFFER;
321
+ #define PQ_DEFINE_MLDSA_SIGN_KEYPAIR(prefix, pqclean) \
322
+ int pq_##prefix##_keypair(uint8_t *public_key, uint8_t *secret_key) { \
323
+ return PQCLEAN_##pqclean##_crypto_sign_keypair(public_key, secret_key) == 0 \
324
+ ? PQ_SUCCESS \
325
+ : PQ_ERROR_KEYPAIR; \
326
+ }
327
+
328
+ PQ_DEFINE_MLDSA_SIGN_KEYPAIR(sign, MLDSA65_CLEAN)
329
+ PQ_DEFINE_MLDSA_SIGN_KEYPAIR(mldsa44_sign, MLDSA44_CLEAN)
330
+ PQ_DEFINE_MLDSA_SIGN_KEYPAIR(mldsa87_sign, MLDSA87_CLEAN)
331
+
332
+ #undef PQ_DEFINE_MLDSA_SIGN_KEYPAIR
333
+
334
+ #define PQ_DEFINE_MLDSA_SIGN(name, pqclean) \
335
+ int pq_##name(uint8_t *signature, size_t *signature_len, const uint8_t *message, \
336
+ size_t message_len, const uint8_t *secret_key) { \
337
+ return PQCLEAN_##pqclean##_crypto_sign_signature(signature, signature_len, message, \
338
+ message_len, secret_key) == 0 \
339
+ ? PQ_SUCCESS \
340
+ : PQ_ERROR_SIGN; \
322
341
  }
323
342
 
324
- if (seed_len != 32) {
343
+ PQ_DEFINE_MLDSA_SIGN(sign, MLDSA65_CLEAN)
344
+ PQ_DEFINE_MLDSA_SIGN(mldsa44_sign, MLDSA44_CLEAN)
345
+ PQ_DEFINE_MLDSA_SIGN(mldsa87_sign, MLDSA87_CLEAN)
346
+
347
+ #undef PQ_DEFINE_MLDSA_SIGN
348
+
349
+ #define PQ_DEFINE_MLDSA_VERIFY(name, pqclean) \
350
+ int pq_##name(const uint8_t *signature, size_t signature_len, const uint8_t *message, \
351
+ size_t message_len, const uint8_t *public_key) { \
352
+ return PQCLEAN_##pqclean##_crypto_sign_verify(signature, signature_len, message, \
353
+ message_len, public_key) == 0 \
354
+ ? PQ_SUCCESS \
355
+ : PQ_ERROR_VERIFY; \
356
+ }
357
+
358
+ PQ_DEFINE_MLDSA_VERIFY(verify, MLDSA65_CLEAN)
359
+ PQ_DEFINE_MLDSA_VERIFY(mldsa44_verify, MLDSA44_CLEAN)
360
+ PQ_DEFINE_MLDSA_VERIFY(mldsa87_verify, MLDSA87_CLEAN)
361
+
362
+ #undef PQ_DEFINE_MLDSA_VERIFY
363
+
364
+ static int pq_testing_mldsa_keypair_from_seed_with(uint8_t *public_key, uint8_t *secret_key,
365
+ const uint8_t *seed, size_t seed_len,
366
+ int (*keypair)(uint8_t *, uint8_t *)) {
367
+ int rc;
368
+ if (!public_key || !secret_key || !seed || seed_len != 32 || !keypair) {
325
369
  return PQ_ERROR_BUFFER;
326
370
  }
327
371
 
328
372
  pq_testing_set_seed(seed, seed_len);
329
- rc = PQCLEAN_MLDSA65_CLEAN_crypto_sign_keypair(public_key, secret_key);
373
+ rc = keypair(public_key, secret_key);
330
374
  pq_testing_clear_seed();
331
375
  return rc == 0 ? PQ_SUCCESS : PQ_ERROR_KEYPAIR;
332
376
  }
333
377
 
334
- int pq_testing_mldsa_sign_from_seed(uint8_t *signature, size_t *signature_len,
335
- const uint8_t *message, size_t message_len,
336
- const uint8_t *secret_key, const uint8_t *seed,
337
- size_t seed_len) {
378
+ static int pq_testing_mldsa_sign_from_seed_with(
379
+ uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len,
380
+ const uint8_t *secret_key, const uint8_t *seed, size_t seed_len,
381
+ int (*sign)(uint8_t *, size_t *, const uint8_t *, size_t, const uint8_t *)) {
338
382
  int rc;
339
- if (!signature || !signature_len || !secret_key || !seed) {
340
- return PQ_ERROR_BUFFER;
341
- }
342
-
343
- if (seed_len != 32) {
383
+ if (!signature || !signature_len || !secret_key || !seed || seed_len != 32 || !sign) {
344
384
  return PQ_ERROR_BUFFER;
345
385
  }
346
386
 
347
387
  pq_testing_set_seed(seed, seed_len);
348
- rc = PQCLEAN_MLDSA65_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len,
349
- secret_key);
388
+ rc = sign(signature, signature_len, message, message_len, secret_key);
350
389
  pq_testing_clear_seed();
351
390
  return rc == 0 ? PQ_SUCCESS : PQ_ERROR_SIGN;
352
391
  }
353
392
 
393
+ /*
394
+ * Production ML-DSA seed expansion for RFC 9881 seed-format PKCS#8 imports.
395
+ *
396
+ * PQClean does not expose a public crypto_sign_keypair_derand entrypoint for
397
+ * ML-DSA. This deliberately reuses pq_crypto's thread-local seed-replay
398
+ * randombytes() path, the same path covered by Patch 8 KATs, and is surfaced
399
+ * only through the Ruby PKCS#8 opt-in gate.
400
+ */
401
+ int pq_mldsa44_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key, const uint8_t *seed32) {
402
+ return pq_testing_mldsa_keypair_from_seed_with(public_key, secret_key, seed32, 32,
403
+ PQCLEAN_MLDSA44_CLEAN_crypto_sign_keypair);
404
+ }
405
+
406
+ int pq_mldsa_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key, const uint8_t *seed32) {
407
+ return pq_testing_mldsa_keypair_from_seed_with(public_key, secret_key, seed32, 32,
408
+ PQCLEAN_MLDSA65_CLEAN_crypto_sign_keypair);
409
+ }
410
+
411
+ int pq_mldsa87_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key, const uint8_t *seed32) {
412
+ return pq_testing_mldsa_keypair_from_seed_with(public_key, secret_key, seed32, 32,
413
+ PQCLEAN_MLDSA87_CLEAN_crypto_sign_keypair);
414
+ }
415
+
416
+ int pq_testing_mldsa_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
417
+ const uint8_t *seed, size_t seed_len) {
418
+ return pq_testing_mldsa_keypair_from_seed_with(public_key, secret_key, seed, seed_len,
419
+ PQCLEAN_MLDSA65_CLEAN_crypto_sign_keypair);
420
+ }
421
+
422
+ int pq_testing_mldsa44_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
423
+ const uint8_t *seed, size_t seed_len) {
424
+ return pq_testing_mldsa_keypair_from_seed_with(public_key, secret_key, seed, seed_len,
425
+ PQCLEAN_MLDSA44_CLEAN_crypto_sign_keypair);
426
+ }
427
+
428
+ int pq_testing_mldsa87_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
429
+ const uint8_t *seed, size_t seed_len) {
430
+ return pq_testing_mldsa_keypair_from_seed_with(public_key, secret_key, seed, seed_len,
431
+ PQCLEAN_MLDSA87_CLEAN_crypto_sign_keypair);
432
+ }
433
+
434
+ int pq_testing_mldsa_sign_from_seed(uint8_t *signature, size_t *signature_len,
435
+ const uint8_t *message, size_t message_len,
436
+ const uint8_t *secret_key, const uint8_t *seed,
437
+ size_t seed_len) {
438
+ return pq_testing_mldsa_sign_from_seed_with(signature, signature_len, message, message_len,
439
+ secret_key, seed, seed_len,
440
+ PQCLEAN_MLDSA65_CLEAN_crypto_sign_signature);
441
+ }
442
+
443
+ int pq_testing_mldsa44_sign_from_seed(uint8_t *signature, size_t *signature_len,
444
+ const uint8_t *message, size_t message_len,
445
+ const uint8_t *secret_key, const uint8_t *seed,
446
+ size_t seed_len) {
447
+ return pq_testing_mldsa_sign_from_seed_with(signature, signature_len, message, message_len,
448
+ secret_key, seed, seed_len,
449
+ PQCLEAN_MLDSA44_CLEAN_crypto_sign_signature);
450
+ }
451
+
452
+ int pq_testing_mldsa87_sign_from_seed(uint8_t *signature, size_t *signature_len,
453
+ const uint8_t *message, size_t message_len,
454
+ const uint8_t *secret_key, const uint8_t *seed,
455
+ size_t seed_len) {
456
+ return pq_testing_mldsa_sign_from_seed_with(signature, signature_len, message, message_len,
457
+ secret_key, seed, seed_len,
458
+ PQCLEAN_MLDSA87_CLEAN_crypto_sign_signature);
459
+ }
460
+
354
461
  int pq_hybrid_kem_keypair(uint8_t *public_key, uint8_t *secret_key) {
355
462
  hybrid_public_key_t pk;
356
463
  hybrid_expanded_secret_key_t expanded;
@@ -959,5 +1066,5 @@ int pq_secret_key_from_pqc_container_pem(char **algorithm_out, uint8_t **key_out
959
1066
  }
960
1067
 
961
1068
  const char *pq_version(void) {
962
- return "0.3.2";
1069
+ return PQCRYPTO_VERSION;
963
1070
  }
@@ -11,14 +11,42 @@
11
11
 
12
12
  #include "mlkem_api.h"
13
13
  #include "mldsa_api.h"
14
- #define MLKEM_PUBLICKEYBYTES PQCLEAN_MLKEM768_CLEAN_CRYPTO_PUBLICKEYBYTES
15
- #define MLKEM_SECRETKEYBYTES PQCLEAN_MLKEM768_CLEAN_CRYPTO_SECRETKEYBYTES
16
- #define MLKEM_CIPHERTEXTBYTES PQCLEAN_MLKEM768_CLEAN_CRYPTO_CIPHERTEXTBYTES
17
- #define MLKEM_SHAREDSECRETBYTES PQCLEAN_MLKEM768_CLEAN_CRYPTO_BYTES
18
14
 
19
- #define MLDSA_PUBLICKEYBYTES 1952
20
- #define MLDSA_SECRETKEYBYTES 4032
21
- #define MLDSA_BYTES 3309
15
+ #define MLKEM512_PUBLICKEYBYTES PQCLEAN_MLKEM512_CLEAN_CRYPTO_PUBLICKEYBYTES
16
+ #define MLKEM512_SECRETKEYBYTES PQCLEAN_MLKEM512_CLEAN_CRYPTO_SECRETKEYBYTES
17
+ #define MLKEM512_CIPHERTEXTBYTES PQCLEAN_MLKEM512_CLEAN_CRYPTO_CIPHERTEXTBYTES
18
+ #define MLKEM512_SHAREDSECRETBYTES PQCLEAN_MLKEM512_CLEAN_CRYPTO_BYTES
19
+
20
+ #define MLKEM768_PUBLICKEYBYTES PQCLEAN_MLKEM768_CLEAN_CRYPTO_PUBLICKEYBYTES
21
+ #define MLKEM768_SECRETKEYBYTES PQCLEAN_MLKEM768_CLEAN_CRYPTO_SECRETKEYBYTES
22
+ #define MLKEM768_CIPHERTEXTBYTES PQCLEAN_MLKEM768_CLEAN_CRYPTO_CIPHERTEXTBYTES
23
+ #define MLKEM768_SHAREDSECRETBYTES PQCLEAN_MLKEM768_CLEAN_CRYPTO_BYTES
24
+
25
+ #define MLKEM1024_PUBLICKEYBYTES PQCLEAN_MLKEM1024_CLEAN_CRYPTO_PUBLICKEYBYTES
26
+ #define MLKEM1024_SECRETKEYBYTES PQCLEAN_MLKEM1024_CLEAN_CRYPTO_SECRETKEYBYTES
27
+ #define MLKEM1024_CIPHERTEXTBYTES PQCLEAN_MLKEM1024_CLEAN_CRYPTO_CIPHERTEXTBYTES
28
+ #define MLKEM1024_SHAREDSECRETBYTES PQCLEAN_MLKEM1024_CLEAN_CRYPTO_BYTES
29
+
30
+ #define MLKEM_PUBLICKEYBYTES MLKEM768_PUBLICKEYBYTES
31
+ #define MLKEM_SECRETKEYBYTES MLKEM768_SECRETKEYBYTES
32
+ #define MLKEM_CIPHERTEXTBYTES MLKEM768_CIPHERTEXTBYTES
33
+ #define MLKEM_SHAREDSECRETBYTES MLKEM768_SHAREDSECRETBYTES
34
+
35
+ #define MLDSA44_PUBLICKEYBYTES PQCLEAN_MLDSA44_CLEAN_CRYPTO_PUBLICKEYBYTES
36
+ #define MLDSA44_SECRETKEYBYTES PQCLEAN_MLDSA44_CLEAN_CRYPTO_SECRETKEYBYTES
37
+ #define MLDSA44_BYTES PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES
38
+
39
+ #define MLDSA65_PUBLICKEYBYTES PQCLEAN_MLDSA65_CLEAN_CRYPTO_PUBLICKEYBYTES
40
+ #define MLDSA65_SECRETKEYBYTES PQCLEAN_MLDSA65_CLEAN_CRYPTO_SECRETKEYBYTES
41
+ #define MLDSA65_BYTES PQCLEAN_MLDSA65_CLEAN_CRYPTO_BYTES
42
+
43
+ #define MLDSA87_PUBLICKEYBYTES PQCLEAN_MLDSA87_CLEAN_CRYPTO_PUBLICKEYBYTES
44
+ #define MLDSA87_SECRETKEYBYTES PQCLEAN_MLDSA87_CLEAN_CRYPTO_SECRETKEYBYTES
45
+ #define MLDSA87_BYTES PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES
46
+
47
+ #define MLDSA_PUBLICKEYBYTES MLDSA65_PUBLICKEYBYTES
48
+ #define MLDSA_SECRETKEYBYTES MLDSA65_SECRETKEYBYTES
49
+ #define MLDSA_BYTES MLDSA65_BYTES
22
50
 
23
51
  #define X25519_PUBLICKEYBYTES 32
24
52
  #define X25519_SECRETKEYBYTES 32
@@ -78,15 +106,45 @@ _Static_assert(sizeof(hybrid_ciphertext_t) == HYBRID_CIPHERTEXTBYTES,
78
106
  void pq_secure_wipe(void *ptr, size_t len);
79
107
 
80
108
  int pq_mlkem_keypair(uint8_t *public_key, uint8_t *secret_key);
109
+ int pq_mlkem512_keypair(uint8_t *public_key, uint8_t *secret_key);
110
+ int pq_mlkem1024_keypair(uint8_t *public_key, uint8_t *secret_key);
111
+ int pq_mlkem_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
112
+ const uint8_t *seed64);
113
+ int pq_mlkem512_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
114
+ const uint8_t *seed64);
115
+ int pq_mlkem1024_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
116
+ const uint8_t *seed64);
81
117
  int pq_mlkem_encapsulate(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
118
+ int pq_mlkem512_encapsulate(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
119
+ int pq_mlkem1024_encapsulate(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
82
120
  int pq_mlkem_decapsulate(uint8_t *shared_secret, const uint8_t *ciphertext,
83
121
  const uint8_t *secret_key);
122
+ int pq_mlkem512_decapsulate(uint8_t *shared_secret, const uint8_t *ciphertext,
123
+ const uint8_t *secret_key);
124
+ int pq_mlkem1024_decapsulate(uint8_t *shared_secret, const uint8_t *ciphertext,
125
+ const uint8_t *secret_key);
84
126
 
85
127
  int pq_sign_keypair(uint8_t *public_key, uint8_t *secret_key);
128
+ int pq_mldsa44_sign_keypair(uint8_t *public_key, uint8_t *secret_key);
129
+ int pq_mldsa87_sign_keypair(uint8_t *public_key, uint8_t *secret_key);
130
+ int pq_mldsa44_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
131
+ const uint8_t *seed32);
132
+ int pq_mldsa_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
133
+ const uint8_t *seed32);
134
+ int pq_mldsa87_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
135
+ const uint8_t *seed32);
86
136
  int pq_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len,
87
137
  const uint8_t *secret_key);
138
+ int pq_mldsa44_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len,
139
+ const uint8_t *secret_key);
140
+ int pq_mldsa87_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len,
141
+ const uint8_t *secret_key);
88
142
  int pq_verify(const uint8_t *signature, size_t signature_len, const uint8_t *message,
89
143
  size_t message_len, const uint8_t *public_key);
144
+ int pq_mldsa44_verify(const uint8_t *signature, size_t signature_len, const uint8_t *message,
145
+ size_t message_len, const uint8_t *public_key);
146
+ int pq_mldsa87_verify(const uint8_t *signature, size_t signature_len, const uint8_t *message,
147
+ size_t message_len, const uint8_t *public_key);
90
148
 
91
149
  int pq_public_key_to_pqc_container_der(uint8_t **output, size_t *output_len,
92
150
  const uint8_t *public_key,
@@ -115,15 +173,37 @@ int pq_secret_key_from_pqc_container_pem(char **algorithm_out, uint8_t **key_out
115
173
 
116
174
  int pq_testing_mlkem_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
117
175
  const uint8_t *seed, size_t seed_len);
176
+ int pq_testing_mlkem512_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
177
+ const uint8_t *seed, size_t seed_len);
178
+ int pq_testing_mlkem1024_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
179
+ const uint8_t *seed, size_t seed_len);
118
180
  int pq_testing_mlkem_encapsulate_from_seed(uint8_t *ciphertext, uint8_t *shared_secret,
119
181
  const uint8_t *public_key, const uint8_t *seed,
120
182
  size_t seed_len);
183
+ int pq_testing_mlkem512_encapsulate_from_seed(uint8_t *ciphertext, uint8_t *shared_secret,
184
+ const uint8_t *public_key, const uint8_t *seed,
185
+ size_t seed_len);
186
+ int pq_testing_mlkem1024_encapsulate_from_seed(uint8_t *ciphertext, uint8_t *shared_secret,
187
+ const uint8_t *public_key, const uint8_t *seed,
188
+ size_t seed_len);
121
189
  int pq_testing_mldsa_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
122
190
  const uint8_t *seed, size_t seed_len);
191
+ int pq_testing_mldsa44_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
192
+ const uint8_t *seed, size_t seed_len);
193
+ int pq_testing_mldsa87_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
194
+ const uint8_t *seed, size_t seed_len);
123
195
  int pq_testing_mldsa_sign_from_seed(uint8_t *signature, size_t *signature_len,
124
196
  const uint8_t *message, size_t message_len,
125
197
  const uint8_t *secret_key, const uint8_t *seed,
126
198
  size_t seed_len);
199
+ int pq_testing_mldsa44_sign_from_seed(uint8_t *signature, size_t *signature_len,
200
+ const uint8_t *message, size_t message_len,
201
+ const uint8_t *secret_key, const uint8_t *seed,
202
+ size_t seed_len);
203
+ int pq_testing_mldsa87_sign_from_seed(uint8_t *signature, size_t *signature_len,
204
+ const uint8_t *message, size_t message_len,
205
+ const uint8_t *secret_key, const uint8_t *seed,
206
+ size_t seed_len);
127
207
 
128
208
  void pq_testing_set_seed(const uint8_t *seed, size_t len);
129
209
  void pq_testing_clear_seed(void);
@@ -0,0 +1,7 @@
1
+ /* Generated by extconf.rb from lib/pq_crypto/version.rb. Do not edit. */
2
+ #ifndef PQCRYPTO_VERSION_H
3
+ #define PQCRYPTO_VERSION_H
4
+
5
+ #define PQCRYPTO_VERSION "0.4.2"
6
+
7
+ #endif
@@ -2,4 +2,4 @@ pqclean_version=2cc64716044832eea747234ddbffc06746ab815d
2
2
  pqclean_url=https://github.com/PQClean/PQClean/archive/2cc64716044832eea747234ddbffc06746ab815d.tar.gz
3
3
  pqclean_archive_sha256=0e92076a79082a8d220e27227f37b280fb2ce050af412babd2bc755ab37b871a
4
4
  pqclean_strip=PQClean-2cc64716044832eea747234ddbffc06746ab815d
5
- pqclean_tree_sha256=2af0c3ec2cbe3b06805c39d3d1389ee7a9b0b29a83183328374a0db55f56c19e
5
+ pqclean_tree_sha256=14a141198236603be48b637021edfd1fca9970cae41bcfd76a9e9aa18823eaad
@@ -0,0 +1,5 @@
1
+ Public Domain (https://creativecommons.org/share-your-work/public-domain/cc0/)
2
+
3
+ For Keccak and AES we are using public-domain
4
+ code from sources and by authors listed in
5
+ comments on top of the respective files.
@@ -0,0 +1,19 @@
1
+ # This Makefile can be used with GNU Make or BSD Make
2
+
3
+ LIB=libml-kem-1024_clean.a
4
+ HEADERS=api.h cbd.h indcpa.h kem.h ntt.h params.h poly.h polyvec.h reduce.h symmetric.h verify.h
5
+ OBJECTS=cbd.o indcpa.o kem.o ntt.o poly.o polyvec.o reduce.o symmetric-shake.o verify.o
6
+
7
+ CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS)
8
+
9
+ all: $(LIB)
10
+
11
+ %.o: %.c $(HEADERS)
12
+ $(CC) $(CFLAGS) -c -o $@ $<
13
+
14
+ $(LIB): $(OBJECTS)
15
+ $(AR) -r $@ $(OBJECTS)
16
+
17
+ clean:
18
+ $(RM) $(OBJECTS)
19
+ $(RM) $(LIB)
@@ -0,0 +1,23 @@
1
+ # This Makefile can be used with Microsoft Visual Studio's nmake using the command:
2
+ # nmake /f Makefile.Microsoft_nmake
3
+
4
+ LIBRARY=libml-kem-1024_clean.lib
5
+ OBJECTS=cbd.obj indcpa.obj kem.obj ntt.obj poly.obj polyvec.obj reduce.obj symmetric-shake.obj verify.obj
6
+
7
+ # Warning C4146 is raised when a unary minus operator is applied to an
8
+ # unsigned type; this has nonetheless been standard and portable for as
9
+ # long as there has been a C standard, and we need it for constant-time
10
+ # computations. Thus, we disable that spurious warning.
11
+ CFLAGS=/nologo /O2 /I ..\..\..\common /W4 /WX /wd4146
12
+
13
+ all: $(LIBRARY)
14
+
15
+ # Make sure objects are recompiled if headers change.
16
+ $(OBJECTS): *.h
17
+
18
+ $(LIBRARY): $(OBJECTS)
19
+ LIB.EXE /NOLOGO /WX /OUT:$@ $**
20
+
21
+ clean:
22
+ -DEL $(OBJECTS)
23
+ -DEL $(LIBRARY)
@@ -0,0 +1,18 @@
1
+ #ifndef PQCLEAN_MLKEM1024_CLEAN_API_H
2
+ #define PQCLEAN_MLKEM1024_CLEAN_API_H
3
+
4
+ #include <stdint.h>
5
+
6
+ #define PQCLEAN_MLKEM1024_CLEAN_CRYPTO_SECRETKEYBYTES 3168
7
+ #define PQCLEAN_MLKEM1024_CLEAN_CRYPTO_PUBLICKEYBYTES 1568
8
+ #define PQCLEAN_MLKEM1024_CLEAN_CRYPTO_CIPHERTEXTBYTES 1568
9
+ #define PQCLEAN_MLKEM1024_CLEAN_CRYPTO_BYTES 32
10
+ #define PQCLEAN_MLKEM1024_CLEAN_CRYPTO_ALGNAME "ML-KEM-1024"
11
+
12
+ int PQCLEAN_MLKEM1024_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
13
+
14
+ int PQCLEAN_MLKEM1024_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
15
+
16
+ int PQCLEAN_MLKEM1024_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
17
+
18
+ #endif
@@ -0,0 +1,83 @@
1
+ #include "cbd.h"
2
+ #include "params.h"
3
+ #include <stdint.h>
4
+
5
+ /*************************************************
6
+ * Name: load32_littleendian
7
+ *
8
+ * Description: load 4 bytes into a 32-bit integer
9
+ * in little-endian order
10
+ *
11
+ * Arguments: - const uint8_t *x: pointer to input byte array
12
+ *
13
+ * Returns 32-bit unsigned integer loaded from x
14
+ **************************************************/
15
+ static uint32_t load32_littleendian(const uint8_t x[4]) {
16
+ uint32_t r;
17
+ r = (uint32_t)x[0];
18
+ r |= (uint32_t)x[1] << 8;
19
+ r |= (uint32_t)x[2] << 16;
20
+ r |= (uint32_t)x[3] << 24;
21
+ return r;
22
+ }
23
+
24
+ /*************************************************
25
+ * Name: load24_littleendian
26
+ *
27
+ * Description: load 3 bytes into a 32-bit integer
28
+ * in little-endian order.
29
+ * This function is only needed for Kyber-512
30
+ *
31
+ * Arguments: - const uint8_t *x: pointer to input byte array
32
+ *
33
+ * Returns 32-bit unsigned integer loaded from x (most significant byte is zero)
34
+ **************************************************/
35
+
36
+
37
+ /*************************************************
38
+ * Name: cbd2
39
+ *
40
+ * Description: Given an array of uniformly random bytes, compute
41
+ * polynomial with coefficients distributed according to
42
+ * a centered binomial distribution with parameter eta=2
43
+ *
44
+ * Arguments: - poly *r: pointer to output polynomial
45
+ * - const uint8_t *buf: pointer to input byte array
46
+ **************************************************/
47
+ static void cbd2(poly *r, const uint8_t buf[2 * KYBER_N / 4]) {
48
+ unsigned int i, j;
49
+ uint32_t t, d;
50
+ int16_t a, b;
51
+
52
+ for (i = 0; i < KYBER_N / 8; i++) {
53
+ t = load32_littleendian(buf + 4 * i);
54
+ d = t & 0x55555555;
55
+ d += (t >> 1) & 0x55555555;
56
+
57
+ for (j = 0; j < 8; j++) {
58
+ a = (d >> (4 * j + 0)) & 0x3;
59
+ b = (d >> (4 * j + 2)) & 0x3;
60
+ r->coeffs[8 * i + j] = a - b;
61
+ }
62
+ }
63
+ }
64
+
65
+ /*************************************************
66
+ * Name: cbd3
67
+ *
68
+ * Description: Given an array of uniformly random bytes, compute
69
+ * polynomial with coefficients distributed according to
70
+ * a centered binomial distribution with parameter eta=3.
71
+ * This function is only needed for Kyber-512
72
+ *
73
+ * Arguments: - poly *r: pointer to output polynomial
74
+ * - const uint8_t *buf: pointer to input byte array
75
+ **************************************************/
76
+
77
+ void PQCLEAN_MLKEM1024_CLEAN_poly_cbd_eta1(poly *r, const uint8_t buf[KYBER_ETA1 * KYBER_N / 4]) {
78
+ cbd2(r, buf);
79
+ }
80
+
81
+ void PQCLEAN_MLKEM1024_CLEAN_poly_cbd_eta2(poly *r, const uint8_t buf[KYBER_ETA2 * KYBER_N / 4]) {
82
+ cbd2(r, buf);
83
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef PQCLEAN_MLKEM1024_CLEAN_CBD_H
2
+ #define PQCLEAN_MLKEM1024_CLEAN_CBD_H
3
+ #include "params.h"
4
+ #include "poly.h"
5
+ #include <stdint.h>
6
+
7
+ void PQCLEAN_MLKEM1024_CLEAN_poly_cbd_eta1(poly *r, const uint8_t buf[KYBER_ETA1 * KYBER_N / 4]);
8
+
9
+ void PQCLEAN_MLKEM1024_CLEAN_poly_cbd_eta2(poly *r, const uint8_t buf[KYBER_ETA2 * KYBER_N / 4]);
10
+
11
+ #endif