pq_crypto 0.6.5 → 0.6.7

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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +233 -0
  3. data/README.md +16 -3
  4. data/SECURITY.md +46 -0
  5. data/ext/pqcrypto/extconf.rb +8 -1
  6. data/ext/pqcrypto/pq_externalmu.c +35 -0
  7. data/ext/pqcrypto/pqcrypto_native_api.h +91 -75
  8. data/ext/pqcrypto/pqcrypto_ruby_secure.c +97 -9
  9. data/ext/pqcrypto/pqcrypto_secure.c +95 -33
  10. data/ext/pqcrypto/pqcrypto_secure.h +66 -48
  11. data/ext/pqcrypto/pqcrypto_version.h +1 -1
  12. data/ext/pqcrypto/vendor/.vendored +7 -7
  13. data/ext/pqcrypto/vendor/mldsa-native/BUILDING.md +5 -2
  14. data/ext/pqcrypto/vendor/mldsa-native/LICENSE +21 -2
  15. data/ext/pqcrypto/vendor/mldsa-native/README.md +20 -7
  16. data/ext/pqcrypto/vendor/mldsa-native/RELEASE.md +160 -0
  17. data/ext/pqcrypto/vendor/mldsa-native/SECURITY.md +1 -1
  18. data/ext/pqcrypto/vendor/mldsa-native/mldsa/README.md +2 -2
  19. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.c +85 -59
  20. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.h +292 -348
  21. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_asm.S +122 -76
  22. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_config.h +184 -86
  23. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/cbmc.h +49 -4
  24. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/common.h +49 -81
  25. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/context.h +152 -0
  26. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.h +25 -12
  27. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.c +2 -0
  28. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.h +2 -0
  29. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +2 -2
  30. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +9 -11
  31. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +19 -11
  32. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_aarch64_asm.S +6 -4
  33. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_aarch64_asm.S +7 -4
  34. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_aarch64_asm.S +7 -4
  35. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_aarch64_asm.S +12 -9
  36. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_aarch64_asm.S +12 -9
  37. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +1 -1
  38. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +3 -2
  39. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +3 -2
  40. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +6 -1
  41. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +3 -2
  42. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/api.h +11 -11
  43. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +9 -22
  44. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +8 -5
  45. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +1 -0
  46. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/{state_extract_bytes_x4_mve.S → keccak_f1600_x4_state_extract_bytes_mve.S} +14 -14
  47. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/{state_xor_bytes_x4_mve.S → keccak_f1600_x4_state_xor_bytes_mve.S} +12 -12
  48. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +5 -4
  49. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +2 -2
  50. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/fips202_native_x86_64.h +1 -0
  51. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2_asm.S +36 -2
  52. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +62 -4
  53. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +87 -54
  54. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{intt_aarch64_asm.S → mldsa_intt_aarch64_asm.S} +39 -6
  55. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{ntt_aarch64_asm.S → mldsa_ntt_aarch64_asm.S} +39 -6
  56. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{pointwise_montgomery_aarch64_asm.S → mldsa_pointwise_montgomery_aarch64_asm.S} +25 -3
  57. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{poly_caddq_aarch64_asm.S → mldsa_poly_caddq_aarch64_asm.S} +19 -3
  58. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{poly_chknorm_aarch64_asm.S → mldsa_poly_chknorm_aarch64_asm.S} +24 -3
  59. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{poly_decompose_32_aarch64_asm.S → mldsa_poly_decompose_32_aarch64_asm.S} +25 -3
  60. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{poly_decompose_88_aarch64_asm.S → mldsa_poly_decompose_88_aarch64_asm.S} +25 -3
  61. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{poly_use_hint_32_aarch64_asm.S → mldsa_poly_use_hint_32_aarch64_asm.S} +25 -3
  62. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{poly_use_hint_88_aarch64_asm.S → mldsa_poly_use_hint_88_aarch64_asm.S} +25 -3
  63. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{mld_polyvecl_pointwise_acc_montgomery_l4_aarch64_asm.S → mldsa_polyvecl_pointwise_acc_montgomery_l4_aarch64_asm.S} +31 -3
  64. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{mld_polyvecl_pointwise_acc_montgomery_l5_aarch64_asm.S → mldsa_polyvecl_pointwise_acc_montgomery_l5_aarch64_asm.S} +31 -3
  65. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{mld_polyvecl_pointwise_acc_montgomery_l7_aarch64_asm.S → mldsa_polyvecl_pointwise_acc_montgomery_l7_aarch64_asm.S} +31 -3
  66. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{polyz_unpack_17_aarch64_asm.S → mldsa_polyz_unpack_17_aarch64_asm.S} +31 -3
  67. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{polyz_unpack_19_aarch64_asm.S → mldsa_polyz_unpack_19_aarch64_asm.S} +31 -3
  68. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{rej_uniform_aarch64_asm.S → mldsa_rej_uniform_aarch64_asm.S} +48 -15
  69. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{rej_uniform_eta2_aarch64_asm.S → mldsa_rej_uniform_eta2_aarch64_asm.S} +42 -9
  70. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/{rej_uniform_eta4_aarch64_asm.S → mldsa_rej_uniform_eta4_aarch64_asm.S} +42 -9
  71. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/api.h +11 -3
  72. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/meta.h +3 -2
  73. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +28 -28
  74. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +171 -49
  75. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/{intt_avx2_asm.S → mldsa_intt_avx2_asm.S} +23 -1
  76. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/{ntt_avx2_asm.S → mldsa_ntt_avx2_asm.S} +23 -1
  77. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/{nttunpack_avx2_asm.S → mldsa_nttunpack_avx2_asm.S} +17 -1
  78. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/{pointwise_acc_l4_avx2_asm.S → mldsa_pointwise_acc_l4_avx2_asm.S} +37 -3
  79. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/{pointwise_acc_l5_avx2_asm.S → mldsa_pointwise_acc_l5_avx2_asm.S} +37 -3
  80. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/{pointwise_acc_l7_avx2_asm.S → mldsa_pointwise_acc_l7_avx2_asm.S} +37 -3
  81. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/{pointwise_avx2_asm.S → mldsa_pointwise_avx2_asm.S} +31 -3
  82. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/{poly_caddq_avx2_asm.S → mldsa_poly_caddq_avx2_asm.S} +18 -9
  83. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_chknorm_avx2_asm.S +176 -0
  84. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_decompose_32_avx2_asm.S +490 -0
  85. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_decompose_88_avx2_asm.S +489 -0
  86. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_use_hint_32_avx2_asm.S +123 -0
  87. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_use_hint_88_avx2_asm.S +125 -0
  88. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_polyz_unpack_17_avx2_asm.S +355 -0
  89. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_polyz_unpack_19_avx2_asm.S +355 -0
  90. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_avx2_asm.S +132 -0
  91. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_eta2_avx2_asm.S +205 -0
  92. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_eta4_avx2_asm.S +176 -0
  93. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.c +27 -36
  94. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.h +42 -8
  95. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/params.h +93 -17
  96. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.c +74 -15
  97. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.h +97 -11
  98. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.c +7 -38
  99. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.h +49 -7
  100. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.c +16 -17
  101. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.h +26 -9
  102. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec_lazy.c +3 -0
  103. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec_lazy.h +18 -19
  104. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/reduce.h +15 -3
  105. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/rounding.h +28 -6
  106. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.c +311 -246
  107. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.h +245 -240
  108. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sys.h +64 -5
  109. data/ext/pqcrypto/vendor/mlkem-native/BUILDING.md +5 -2
  110. data/ext/pqcrypto/vendor/mlkem-native/LICENSE +21 -3
  111. data/ext/pqcrypto/vendor/mlkem-native/README.md +2 -2
  112. data/ext/pqcrypto/vendor/mlkem-native/RELEASE.md +113 -0
  113. data/ext/pqcrypto/vendor/mlkem-native/mlkem/README.md +2 -2
  114. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.c +17 -27
  115. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.h +68 -151
  116. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_asm.S +17 -27
  117. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_config.h +46 -44
  118. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/cbmc.h +25 -0
  119. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/common.h +37 -6
  120. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/context.h +9 -0
  121. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.h +2 -2
  122. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/keccakf1600.c +8 -8
  123. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_scalar.h +1 -1
  124. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_v84a.h +3 -3
  125. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x2_v84a.h +3 -3
  126. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_scalar.h +2 -2
  127. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +3 -3
  128. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/api.h +11 -11
  129. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/mve.h +3 -3
  130. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +2 -2
  131. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.h +14 -11
  132. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.c +28 -11
  133. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.h +39 -14
  134. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/meta.h +10 -10
  135. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/meta.h +20 -20
  136. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sys.h +5 -5
  137. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/verify.h +11 -10
  138. data/lib/pq_crypto/internal.rb +10 -0
  139. data/lib/pq_crypto/kem.rb +47 -5
  140. data/lib/pq_crypto/key.rb +14 -8
  141. data/lib/pq_crypto/pkcs8.rb +13 -5
  142. data/lib/pq_crypto/signature.rb +34 -9
  143. data/lib/pq_crypto/spki.rb +4 -2
  144. data/lib/pq_crypto/version.rb +1 -1
  145. data/lib/pq_crypto.rb +9 -0
  146. data/script/vendor_libs.rb +6 -6
  147. metadata +40 -38
  148. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_chknorm_avx2.c +0 -52
  149. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_32_avx2.c +0 -157
  150. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_88_avx2.c +0 -157
  151. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_32_avx2.c +0 -103
  152. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_88_avx2.c +0 -105
  153. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_17_avx2.c +0 -94
  154. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_19_avx2.c +0 -96
  155. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_avx2.c +0 -126
  156. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta2_avx2.c +0 -157
  157. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta4_avx2.c +0 -141
@@ -2,6 +2,16 @@
2
2
  * Copyright (c) The mldsa-native project authors
3
3
  * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
4
4
  */
5
+
6
+ /* References
7
+ * ==========
8
+ *
9
+ * - [FIPS204]
10
+ * FIPS 204 Module-Lattice-Based Digital Signature Standard
11
+ * National Institute of Standards and Technology
12
+ * https://csrc.nist.gov/pubs/fips/204/final
13
+ */
14
+
5
15
  #ifndef MLD_POLYVEC_H
6
16
  #define MLD_POLYVEC_H
7
17
 
@@ -31,20 +41,22 @@ typedef struct
31
41
  /**
32
42
  * Sample vector of polynomials with uniformly random coefficients in
33
43
  * [-(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1] by unpacking output stream of
34
- * SHAKE256(seed|nonce).
44
+ * SHAKE256(seed|kappa+i) for component i.
45
+ *
46
+ * @spec{Implements @[FIPS204, Algorithm 34, ExpandMask].}
35
47
  *
36
48
  * @param[out] v Pointer to output vector.
37
49
  * @param[in] seed Byte array with seed of length MLDSA_CRHBYTES.
38
- * @param nonce 16-bit nonce.
50
+ * @param kappa Base counter; component i uses kappa + i.
39
51
  */
40
52
  MLD_INTERNAL_API
41
53
  void mld_polyvecl_uniform_gamma1(mld_polyvecl *v,
42
54
  const uint8_t seed[MLDSA_CRHBYTES],
43
- uint16_t nonce)
55
+ uint16_t kappa)
44
56
  __contract__(
45
57
  requires(memory_no_alias(v, sizeof(mld_polyvecl)))
46
58
  requires(memory_no_alias(seed, MLDSA_CRHBYTES))
47
- requires(nonce <= (UINT16_MAX - MLDSA_L) / MLDSA_L)
59
+ requires(kappa <= MLD_MAX_KAPPA)
48
60
  assigns(memory_slice(v, sizeof(mld_polyvecl)))
49
61
  ensures(forall(k0, 0, MLDSA_L,
50
62
  array_bound(v->vec[k0].coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1)))
@@ -58,8 +70,8 @@ __contract__(
58
70
  (!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST)))
59
71
  #define mld_polyvecl_ntt MLD_NAMESPACE_KL(polyvecl_ntt)
60
72
  /**
61
- * Forward NTT of all polynomials in vector of length MLDSA_L. Coefficients
62
- * can grow by 8*MLDSA_Q in absolute value.
73
+ * Forward NTT of all polynomials in vector of length MLDSA_L. Output
74
+ * coefficients are bounded by MLD_NTT_BOUND in absolute value.
63
75
  *
64
76
  * @param[in,out] v Pointer to input/output vector.
65
77
  */
@@ -87,7 +99,10 @@ __contract__(
87
99
  * have coefficients in [0, MLDSA_Q-1] inclusive.
88
100
  *
89
101
  * The second input "v" is assumed to be output of an NTT, and hence must have
90
- * coefficients bounded by [-(9*MLDSA_Q-1), 9*MLDSA_Q-1] inclusive.
102
+ * coefficients bounded by [-(MLD_NTT_BOUND-1), MLD_NTT_BOUND-1] inclusive.
103
+ *
104
+ * @spec{Partially implements @[FIPS204, Algorithm 48, MatrixVectorNTT]
105
+ * (one output polynomial; multiply-accumulate of two NTT-domain vectors).}
91
106
  *
92
107
  * @param[out] w Output polynomial.
93
108
  * @param[in] u Pointer to first input vector.
@@ -186,8 +201,8 @@ __contract__(
186
201
  (!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST))
187
202
  #define mld_polyveck_ntt MLD_NAMESPACE_KL(polyveck_ntt)
188
203
  /**
189
- * Forward NTT of all polynomials in vector of length MLDSA_K. Coefficients
190
- * can grow by 8*MLDSA_Q in absolute value.
204
+ * Forward NTT of all polynomials in vector of length MLDSA_K. Output
205
+ * coefficients are bounded by MLD_NTT_BOUND in absolute value.
191
206
  *
192
207
  * @param[in,out] v Pointer to input/output vector.
193
208
  */
@@ -290,6 +305,8 @@ __contract__(
290
305
  * Bit-pack polynomial vector w1 with coefficients in [0, 15] or [0, 43]. Input
291
306
  * coefficients are assumed to be standard representatives.
292
307
  *
308
+ * @spec{Implements @[FIPS204, Algorithm 28, w1Encode].}
309
+ *
293
310
  * @param[out] r Pointer to output byte array with at least
294
311
  * MLDSA_K * MLDSA_POLYW1_PACKEDBYTES bytes.
295
312
  * @param[in] w1 Pointer to input polynomial vector.
@@ -29,6 +29,9 @@
29
29
  * of seed_ext. This function writes the domain-separation bytes
30
30
  * seed_ext[SEEDBYTES..+2] = {l, k} before sampling.
31
31
  *
32
+ * @spec{Partially implements @[FIPS204, Algorithm 32, ExpandA] (samples one
33
+ * matrix entry via @[FIPS204, Algorithm 30, RejNTTPoly]).}
34
+ *
32
35
  * @param[out] p Pointer to output polynomial.
33
36
  * @param[in,out] seed_ext Seed buffer pre-filled with rho in the first
34
37
  * MLDSA_SEEDBYTES; the final two bytes are
@@ -127,11 +127,11 @@ typedef struct
127
127
  mld_polyvecl vec; /**< Masking vector y. */
128
128
  } mld_yvec_eager;
129
129
 
130
- /** Lazy yvec: store seed and nonce, regenerate y[i] on demand. */
130
+ /** Lazy yvec: store seed and base counter kappa, regenerate y[i] on demand. */
131
131
  typedef struct
132
132
  {
133
133
  const uint8_t *rhoprime; /**< Pointer to seed used to derive y. */
134
- uint16_t nonce; /**< Base nonce; component i uses MLDSA_L*nonce + i. */
134
+ uint16_t kappa; /**< Base counter; component i uses kappa + i. */
135
135
  } mld_yvec_lazy;
136
136
 
137
137
  #if !defined(MLD_CONFIG_NO_KEYPAIR_API) || !defined(MLD_CONFIG_NO_SIGN_API)
@@ -341,17 +341,17 @@ __contract__(
341
341
  #if !defined(MLD_CONFIG_NO_SIGN_API) && \
342
342
  (!defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST))
343
343
  static MLD_INLINE void mld_yvec_init_eager(
344
- mld_yvec_eager *y, const uint8_t rhoprime[MLDSA_CRHBYTES], uint16_t nonce)
344
+ mld_yvec_eager *y, const uint8_t rhoprime[MLDSA_CRHBYTES], uint16_t kappa)
345
345
  __contract__(
346
346
  requires(memory_no_alias(y, sizeof(mld_yvec_eager)))
347
347
  requires(memory_no_alias(rhoprime, MLDSA_CRHBYTES))
348
- requires(nonce <= (UINT16_MAX - MLDSA_L) / MLDSA_L)
348
+ requires(kappa <= MLD_MAX_KAPPA)
349
349
  assigns(memory_slice(y, sizeof(mld_yvec_eager)))
350
350
  ensures(forall(k1, 0, MLDSA_L,
351
351
  array_bound(y->vec.vec[k1].coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1)))
352
352
  )
353
353
  {
354
- mld_polyvecl_uniform_gamma1(&y->vec, rhoprime, nonce);
354
+ mld_polyvecl_uniform_gamma1(&y->vec, rhoprime, kappa);
355
355
  }
356
356
 
357
357
  static MLD_INLINE void mld_yvec_get_poly_eager(mld_poly *buf,
@@ -370,16 +370,16 @@ __contract__(
370
370
  #if !defined(MLD_CONFIG_NO_SIGN_API) && \
371
371
  (defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST))
372
372
  static MLD_INLINE void mld_yvec_init_lazy(
373
- mld_yvec_lazy *y, const uint8_t rhoprime[MLDSA_CRHBYTES], uint16_t nonce)
373
+ mld_yvec_lazy *y, const uint8_t rhoprime[MLDSA_CRHBYTES], uint16_t kappa)
374
374
  __contract__(
375
375
  requires(memory_no_alias(y, sizeof(mld_yvec_lazy)))
376
376
  assigns(memory_slice(y, sizeof(mld_yvec_lazy)))
377
377
  ensures(y->rhoprime == old(rhoprime))
378
- ensures(y->nonce == old(nonce))
378
+ ensures(y->kappa == old(kappa))
379
379
  )
380
380
  {
381
381
  y->rhoprime = rhoprime;
382
- y->nonce = nonce;
382
+ y->kappa = kappa;
383
383
  }
384
384
 
385
385
  static MLD_INLINE void mld_yvec_get_poly_lazy(mld_poly *buf,
@@ -390,16 +390,14 @@ __contract__(
390
390
  requires(memory_no_alias(y, sizeof(mld_yvec_lazy)))
391
391
  requires(i < MLDSA_L)
392
392
  requires(memory_no_alias(y->rhoprime, MLDSA_CRHBYTES))
393
- requires(y->nonce <= ((UINT16_MAX - MLDSA_L) / MLDSA_L))
393
+ requires(y->kappa <= MLD_MAX_KAPPA)
394
394
  assigns(memory_slice(buf, sizeof(mld_poly)))
395
395
  ensures(array_bound(buf->coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1))
396
396
  )
397
397
  {
398
- /* Safety: y->nonce is at most ((UINT16_MAX - MLDSA_L) / MLDSA_L) and
399
- * i < MLDSA_L, so MLDSA_L * y->nonce + i fits in uint16_t. See
400
- * MLD_NONCE_UB comment in sign.c. */
401
- mld_poly_uniform_gamma1(buf, y->rhoprime,
402
- (uint16_t)(MLDSA_L * y->nonce + (int)i));
398
+ /* Safety: y->kappa <= MLD_MAX_KAPPA and i < MLDSA_L, so y->kappa + i
399
+ * fits in uint16_t. See MLD_MAX_KAPPA comment in params.h. */
400
+ mld_poly_uniform_gamma1(buf, y->rhoprime, (uint16_t)(y->kappa + i));
403
401
  }
404
402
  #endif /* !MLD_CONFIG_NO_SIGN_API && (MLD_CONFIG_REDUCE_RAM || MLD_UNIT_TEST) \
405
403
  */
@@ -441,9 +439,10 @@ __contract__(
441
439
 
442
440
  #if !defined(MLD_CONFIG_REDUCE_RAM) || defined(MLD_UNIT_TEST)
443
441
  /**
444
- * Implementation of ExpandA. Generates matrix A with uniformly random
445
- * coefficients a_{i,j} by performing rejection sampling on the output stream
446
- * of SHAKE128(rho|j|i).
442
+ * Generates matrix A with uniformly random coefficients a_{i,j} by performing
443
+ * rejection sampling on the output stream of SHAKE128(rho|j|i).
444
+ *
445
+ * @spec{Implements @[FIPS204, Algorithm 32, ExpandA].}
447
446
  *
448
447
  * @param[out] mat Pointer to output matrix.
449
448
  * @param[in] rho Byte array containing seed rho.
@@ -579,7 +578,7 @@ __contract__(
579
578
  *
580
579
  * @param[out] w Pointer to output vector.
581
580
  * @param[in,out] mat Pointer to input matrix.
582
- * @param[in] y Pointer to y seed/nonce.
581
+ * @param[in] y Pointer to y seed/kappa.
583
582
  * @param[out] scratch Scratch (only &scratch->vec[0] used).
584
583
  */
585
584
  MLD_INTERNAL_API
@@ -593,7 +592,7 @@ __contract__(
593
592
  requires(memory_no_alias(y, sizeof(mld_yvec_lazy)))
594
593
  requires(memory_no_alias(scratch, sizeof(mld_polyvecl)))
595
594
  requires(memory_no_alias(y->rhoprime, MLDSA_CRHBYTES))
596
- requires(y->nonce <= ((UINT16_MAX - MLDSA_L) / MLDSA_L))
595
+ requires(y->kappa <= MLD_MAX_KAPPA)
597
596
  assigns(memory_slice(w, sizeof(mld_polyveck)))
598
597
  assigns(memory_slice(mat, sizeof(mld_polymat_lazy)))
599
598
  assigns(memory_slice(scratch, sizeof(mld_polyvecl)))
@@ -2,6 +2,16 @@
2
2
  * Copyright (c) The mldsa-native project authors
3
3
  * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
4
4
  */
5
+
6
+ /* References
7
+ * ==========
8
+ *
9
+ * - [FIPS204]
10
+ * FIPS 204 Module-Lattice-Based Digital Signature Standard
11
+ * National Institute of Standards and Technology
12
+ * https://csrc.nist.gov/pubs/fips/204/final
13
+ */
14
+
5
15
  #ifndef MLD_REDUCE_H
6
16
  #define MLD_REDUCE_H
7
17
 
@@ -11,10 +21,10 @@
11
21
  #include "debug.h"
12
22
 
13
23
  /* check-magic: -4186625 == pow(2,32,MLDSA_Q) */
14
- #define MLD_MONT -4186625
24
+ #define MLD_MONT (-4186625)
15
25
 
16
26
  /* Upper bound for domain of mld_reduce32() */
17
- #define MLD_REDUCE32_DOMAIN_MAX (INT32_MAX - (1 << 22))
27
+ #define MLD_REDUCE32_DOMAIN_MAX (INT32_MAX - ((int32_t)1 << 22))
18
28
 
19
29
  /* Absolute bound for range of mld_reduce32() */
20
30
  /* check-magic: 6283009 == (MLD_REDUCE32_DOMAIN_MAX - 255 * MLDSA_Q + 1) */
@@ -24,6 +34,8 @@
24
34
  * Generic Montgomery reduction; given a 64-bit integer a, computes a 32-bit
25
35
  * integer congruent to a * R^-1 mod MLDSA_Q, where R=2^32.
26
36
  *
37
+ * @spec{Implements @[FIPS204, Algorithm 49, MontgomeryReduce].}
38
+ *
27
39
  * @param a Input integer to be reduced, of absolute value smaller or equal
28
40
  * to INT64_MAX - 2^31 * MLDSA_Q.
29
41
  *
@@ -102,7 +114,7 @@ __contract__(
102
114
  {
103
115
  int32_t t;
104
116
 
105
- t = (a + (1 << 22)) >> 23;
117
+ t = (a + ((int32_t)1 << 22)) >> 23;
106
118
  t = a - t * MLDSA_Q;
107
119
  mld_assert((t - a) % MLDSA_Q == 0);
108
120
  return t;
@@ -38,6 +38,8 @@
38
38
  * -2^{MLDSA_D-1} < a0 <= 2^{MLDSA_D-1}. Assumes a to be standard
39
39
  * representative.
40
40
  *
41
+ * @spec{Implements @[FIPS204, Algorithm 35, Power2Round].}
42
+ *
41
43
  * @reference{In the reference implementation, a1 is passed as a return value
42
44
  * instead.}
43
45
  *
@@ -69,6 +71,8 @@ __contract__(
69
71
  * -MLDSA_GAMMA2 <= a0 = a mod^+ MLDSA_Q - MLDSA_Q < 0. Assumes a to be
70
72
  * standard representative.
71
73
  *
74
+ * @spec{Implements @[FIPS204, Algorithm 36, Decompose].}
75
+ *
72
76
  * @reference{In the reference implementation, a1 is passed as a return value
73
77
  * instead.}
74
78
  *
@@ -83,8 +87,9 @@ __contract__(
83
87
  requires(a >= 0 && a < MLDSA_Q)
84
88
  assigns(memory_slice(a0, sizeof(int32_t)))
85
89
  assigns(memory_slice(a1, sizeof(int32_t)))
86
- /* a0 = -MLDSA_GAMMA2 can only occur when (q-1) = a - (a mod MLDSA_GAMMA2),
87
- * then a1=1; and a0 = a - (a mod MLDSA_GAMMA2) - 1 (@[FIPS204, Algorithm 36 (Decompose)]) */
90
+ /* a0 = -MLDSA_GAMMA2 occurs exactly when a = MLDSA_Q - MLDSA_GAMMA2: the
91
+ * border case of Decompose where a1 = (MLDSA_Q-1)/(2*MLDSA_GAMMA2) is
92
+ * wrapped to 0 and a0 = a - MLDSA_Q (@[FIPS204, Algorithm 36, Decompose]) */
88
93
  ensures(*a0 >= -MLDSA_GAMMA2 && *a0 <= MLDSA_GAMMA2)
89
94
  ensures(*a1 >= 0 && *a1 < (MLDSA_Q-1)/(2*MLDSA_GAMMA2))
90
95
  ensures((*a1 * 2 * MLDSA_GAMMA2 + *a0 - a) % MLDSA_Q == 0)
@@ -141,7 +146,7 @@ __contract__(
141
146
  *
142
147
  * See proofs/isabelle/compress for a formalization of the above argument.
143
148
  */
144
- *a1 = (*a1 * 11275 + (1 << 23)) >> 24;
149
+ *a1 = (*a1 * 11275 + ((int32_t)1 << 23)) >> 24;
145
150
  mld_assert(*a1 >= 0 && *a1 <= 44);
146
151
 
147
152
  *a1 = mld_ct_sel_int32(0, *a1, mld_ct_cmask_neg_i32(43 - *a1));
@@ -157,7 +162,7 @@ __contract__(
157
162
  * eps = 1 / 4290772992 ≈ 2^(-31.99) < 2^(-31), therefore f1' * eps <
158
163
  * 2^16 * 2^(-31) = 1 / 2^15 < 1 / 2^12 < 1 / B.
159
164
  */
160
- *a1 = (*a1 * 1025 + (1 << 21)) >> 22;
165
+ *a1 = (*a1 * 1025 + ((int32_t)1 << 21)) >> 22;
161
166
  mld_assert(*a1 >= 0 && *a1 <= 16);
162
167
 
163
168
  *a1 &= 15;
@@ -171,8 +176,21 @@ __contract__(
171
176
  }
172
177
 
173
178
  /**
174
- * Compute hint bit indicating whether the low bits of the input element
175
- * overflow into the high bits.
179
+ * Decide a single hint bit from the low part a0 and high part a1 of a
180
+ * coefficient: return 1 unless a0 lies in the range (-GAMMA2, GAMMA2] that
181
+ * LowBits would produce, with the boundary value -GAMMA2 also admitted when
182
+ * a1 == 0 (the Decompose border case).
183
+ *
184
+ * @note This is not a line-for-line implementation of FIPS 204's MakeHint(z, r)
185
+ * (@[FIPS204, Algorithm 39, MakeHint]), which takes two ring elements and
186
+ * returns [[HighBits(r) != HighBits(r + z)]]. Instead, it takes the already
187
+ * decomposed low/high parts (a0, a1) of a coefficient and decides the hint bit
188
+ * from them directly. As explained in the block comment of
189
+ * mld_attempt_signature_generation (sign.c), for the specific values that arise
190
+ * during signing -- a0 = w0 - cs2 + ct0 and a1 = w1 = HighBits(w) -- this is
191
+ * equivalent to the spec's MakeHint(-ct0, w - cs2 + ct0) coefficient-wise.
192
+ * Because it consumes (a0, a1) rather than (z, r), it relies on the caller
193
+ * having computed a compatible decomposition.
176
194
  *
177
195
  * @param a0 Low bits of input element.
178
196
  * @param a1 High bits of input element.
@@ -183,6 +201,8 @@ MLD_MUST_CHECK_RETURN_VALUE
183
201
  static MLD_INLINE unsigned int mld_make_hint(int32_t a0, int32_t a1)
184
202
  __contract__(
185
203
  ensures(return_value >= 0 && return_value <= 1)
204
+ ensures(return_value == (a0 > MLDSA_GAMMA2 || a0 < -MLDSA_GAMMA2 ||
205
+ (a0 == -MLDSA_GAMMA2 && a1 != 0)))
186
206
  )
187
207
  {
188
208
  if (a0 > MLDSA_GAMMA2 || a0 < -MLDSA_GAMMA2 ||
@@ -197,6 +217,8 @@ __contract__(
197
217
  /**
198
218
  * Correct high bits according to hint.
199
219
  *
220
+ * @spec{Implements @[FIPS204, Algorithm 40, UseHint].}
221
+ *
200
222
  * @param a Input element.
201
223
  * @param hint Hint bit.
202
224
  *