pq_crypto 0.6.2 → 0.6.3

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/ext/pqcrypto/pqcrypto_version.h +1 -1
  4. data/ext/pqcrypto/vendor/.vendored +4 -4
  5. data/ext/pqcrypto/vendor/mlkem-native/README.md +6 -3
  6. data/ext/pqcrypto/vendor/mlkem-native/RELEASE.md +22 -0
  7. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.c +77 -36
  8. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.h +135 -146
  9. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_asm.S +116 -72
  10. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_config.h +351 -415
  11. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/cbmc.h +43 -20
  12. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/common.h +16 -8
  13. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.c +57 -31
  14. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.h +260 -349
  15. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/debug.h +17 -24
  16. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.c +35 -37
  17. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.h +43 -57
  18. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202x4.c +14 -15
  19. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202x4.h +5 -4
  20. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/keccakf1600.c +42 -6
  21. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/fips202_native_aarch64.h +31 -20
  22. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/{keccak_f1600_x1_scalar_asm.S → keccak_f1600_x1_scalar_aarch64_asm.S} +10 -10
  23. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/{keccak_f1600_x1_v84a_asm.S → keccak_f1600_x1_v84a_aarch64_asm.S} +10 -10
  24. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/{keccak_f1600_x2_v84a_asm.S → keccak_f1600_x2_v84a_aarch64_asm.S} +10 -10
  25. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/{keccak_f1600_x4_v8a_scalar_hybrid_asm.S → keccak_f1600_x4_v8a_scalar_hybrid_aarch64_asm.S} +10 -10
  26. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/{keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S → keccak_f1600_x4_v8a_v84a_scalar_hybrid_aarch64_asm.S} +10 -10
  27. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +10 -9
  28. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_scalar.h +2 -1
  29. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_v84a.h +1 -1
  30. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x2_v84a.h +4 -2
  31. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_scalar.h +2 -2
  32. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +1 -1
  33. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/fips202_native_armv81m.h +2 -1
  34. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +55 -9
  35. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +26 -25
  36. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/state_extract_bytes_x4_mve.S +58 -14
  37. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/state_xor_bytes_x4_mve.S +57 -16
  38. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/auto.h +2 -1
  39. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +2 -2
  40. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/fips202_native_x86_64.h +10 -7
  41. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/{keccak_f1600_x4_avx2.S → keccak_f1600_x4_avx2_asm.S} +13 -11
  42. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/keccakf1600_constants.c +12 -11
  43. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.c +167 -136
  44. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.h +75 -68
  45. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.h +135 -157
  46. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/meta.h +15 -13
  47. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/aarch64_zetas.c +143 -135
  48. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/arith_native_aarch64.h +52 -46
  49. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{intt.S → intt_aarch64_asm.S} +10 -10
  50. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{ntt.S → ntt_aarch64_asm.S} +10 -10
  51. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{poly_mulcache_compute_asm.S → poly_mulcache_compute_aarch64_asm.S} +10 -10
  52. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{poly_reduce_asm.S → poly_reduce_aarch64_asm.S} +10 -10
  53. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{poly_tobytes_asm.S → poly_tobytes_aarch64_asm.S} +10 -10
  54. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{poly_tomont_asm.S → poly_tomont_aarch64_asm.S} +10 -12
  55. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{polyvec_basemul_acc_montgomery_cached_asm_k2.S → polyvec_basemul_acc_montgomery_cached_k2_aarch64_asm.S} +10 -10
  56. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{polyvec_basemul_acc_montgomery_cached_asm_k3.S → polyvec_basemul_acc_montgomery_cached_k3_aarch64_asm.S} +10 -10
  57. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{polyvec_basemul_acc_montgomery_cached_asm_k4.S → polyvec_basemul_acc_montgomery_cached_k4_aarch64_asm.S} +10 -10
  58. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{rej_uniform_asm.S → rej_uniform_aarch64_asm.S} +12 -12
  59. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/rej_uniform_table.c +514 -513
  60. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/api.h +254 -253
  61. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/meta.h +6 -1
  62. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/README.md +6 -0
  63. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/meta.h +77 -0
  64. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/arith_native_ppc64le.h +24 -0
  65. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/consts.c +299 -0
  66. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/consts.h +34 -0
  67. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/intt_ppc_asm.S +3222 -0
  68. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/ntt_ppc_asm.S +1651 -0
  69. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/poly_tomont_ppc_asm.S +294 -0
  70. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/reduce_ppc_asm.S +710 -0
  71. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/meta.h +5 -0
  72. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_debug.c +18 -16
  73. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_debug.h +19 -24
  74. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_poly.c +53 -65
  75. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/meta.h +20 -20
  76. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/arith_native_x86_64.h +106 -88
  77. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.c +45 -35
  78. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.h +8 -8
  79. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/consts.c +1 -1
  80. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/consts.h +1 -1
  81. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{intt.S → intt_avx2_asm.S} +8 -8
  82. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{ntt.S → ntt_avx2_asm.S} +8 -8
  83. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{nttfrombytes.S → nttfrombytes_avx2_asm.S} +8 -8
  84. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{ntttobytes.S → ntttobytes_avx2_asm.S} +8 -8
  85. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{nttunpack.S → nttunpack_avx2_asm.S} +8 -8
  86. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_compress_d10.S → poly_compress_d10_avx2_asm.S} +9 -9
  87. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_compress_d11.S → poly_compress_d11_avx2_asm.S} +9 -9
  88. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_compress_d4.S → poly_compress_d4_avx2_asm.S} +9 -9
  89. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_compress_d5.S → poly_compress_d5_avx2_asm.S} +9 -9
  90. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_decompress_d10.S → poly_decompress_d10_avx2_asm.S} +9 -9
  91. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_decompress_d11.S → poly_decompress_d11_avx2_asm.S} +9 -9
  92. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_decompress_d4.S → poly_decompress_d4_avx2_asm.S} +9 -9
  93. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_decompress_d5.S → poly_decompress_d5_avx2_asm.S} +9 -9
  94. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{mulcache_compute.S → poly_mulcache_compute_avx2_asm.S} +8 -8
  95. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{polyvec_basemul_acc_montgomery_cached_asm_k2.S → polyvec_basemul_acc_montgomery_cached_k2_avx2_asm.S} +8 -8
  96. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{polyvec_basemul_acc_montgomery_cached_asm_k3.S → polyvec_basemul_acc_montgomery_cached_k3_avx2_asm.S} +8 -8
  97. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{polyvec_basemul_acc_montgomery_cached_asm_k4.S → polyvec_basemul_acc_montgomery_cached_k4_avx2_asm.S} +8 -8
  98. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{reduce.S → reduce_avx2_asm.S} +8 -8
  99. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{rej_uniform_asm.S → rej_uniform_avx2_asm.S} +9 -9
  100. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/rej_uniform_table.c +514 -513
  101. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{tomont.S → tomont_avx2_asm.S} +8 -8
  102. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.c +61 -57
  103. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.h +89 -116
  104. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.c +31 -32
  105. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.h +226 -301
  106. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/randombytes.h +21 -29
  107. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.c +68 -63
  108. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.h +37 -48
  109. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sys.h +44 -2
  110. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/verify.h +141 -159
  111. data/lib/pq_crypto/version.rb +1 -1
  112. data/script/vendor_libs.rb +3 -3
  113. metadata +47 -38
@@ -8,16 +8,27 @@
8
8
  /***************************************************
9
9
  * Basic replacements for __CPROVER_XXX contracts
10
10
  ***************************************************/
11
+ /*
12
+ * The `__contract__` / `__loop__` annotation macros use a
13
+ * leading-double-underscore spelling in line with other CBMC macros.
14
+ * clang-tidy flags these as reserved identifiers; we suppress the diagnostic
15
+ * at each definition site (NOLINT) rather than disabling the check globally,
16
+ * so it stays active for the rest of the tree.
17
+ */
11
18
  #ifndef CBMC
12
19
 
13
- #define __contract__(x)
14
- #define __loop__(x)
20
+ /* clang-format off */
21
+ #define __contract__(x) /* NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
22
+ #define __loop__(x) /* NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
23
+ /* clang-format on */
15
24
 
16
25
  #else /* !CBMC */
17
26
 
18
27
 
19
- #define __contract__(x) x
20
- #define __loop__(x) x
28
+ /* clang-format off */
29
+ #define __contract__(x) x /* NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
30
+ #define __loop__(x) x /* NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
31
+ /* clang-format on */
21
32
 
22
33
  /* https://diffblue.github.io/cbmc/contracts-assigns.html */
23
34
  #define assigns(...) __CPROVER_assigns(__VA_ARGS__)
@@ -80,24 +91,36 @@
80
91
  * Quantifiers
81
92
  * Note that the range on qvar is _exclusive_ between qvar_lb .. qvar_ub
82
93
  * https://diffblue.github.io/cbmc/contracts-quantifiers.html
94
+ *
95
+ * The quantified variable is declared as uint32_t, so these macros
96
+ * quantify only over indices in [0, UINT32_MAX). Bounds larger than
97
+ * UINT32_MAX (4 GiB) are NOT supported: the explicit (uint32_t) casts
98
+ * on the bounds will trigger CBMC's conversion check if a wider bound
99
+ * (e.g. a size_t > UINT32_MAX) is passed.
100
+ *
101
+ * Quantifying over size_t (64-bit) was found to blow up SMT proof
102
+ * times, so we deliberately keep the index width at 32 bits. Callers
103
+ * dealing with size_t-typed buffers must add an explicit
104
+ * requires(len <= UINT32_MAX)
105
+ * precondition.
83
106
  */
84
107
 
85
108
  /*
86
109
  * Prevent clang-format from corrupting CBMC's special ==> operator
87
110
  */
88
111
  /* clang-format off */
89
- #define forall(qvar, qvar_lb, qvar_ub, predicate) \
90
- __CPROVER_forall \
91
- { \
92
- unsigned qvar; \
93
- ((qvar_lb) <= (qvar) && (qvar) < (qvar_ub)) ==> (predicate) \
112
+ #define forall(qvar, qvar_lb, qvar_ub, predicate) \
113
+ __CPROVER_forall \
114
+ { \
115
+ uint32_t qvar; \
116
+ ((uint32_t) (qvar_lb) <= (qvar) && (qvar) < (uint32_t) (qvar_ub)) ==> (predicate) \
94
117
  }
95
118
 
96
- #define exists(qvar, qvar_lb, qvar_ub, predicate) \
97
- __CPROVER_exists \
98
- { \
99
- unsigned qvar; \
100
- ((qvar_lb) <= (qvar) && (qvar) < (qvar_ub)) && (predicate) \
119
+ #define exists(qvar, qvar_lb, qvar_ub, predicate) \
120
+ __CPROVER_exists \
121
+ { \
122
+ uint32_t qvar; \
123
+ ((uint32_t) (qvar_lb) <= (qvar) && (qvar) < (uint32_t) (qvar_ub)) && (predicate) \
101
124
  }
102
125
  /* clang-format on */
103
126
 
@@ -126,8 +149,8 @@
126
149
  value_lb, value_ub) \
127
150
  __CPROVER_forall \
128
151
  { \
129
- unsigned qvar; \
130
- ((qvar_lb) <= (qvar) && (qvar) < (qvar_ub)) ==> \
152
+ uint32_t qvar; \
153
+ ((uint32_t) (qvar_lb) <= (qvar) && (qvar) < (uint32_t) (qvar_ub)) ==> \
131
154
  (((int)(value_lb) <= ((array_var)[(qvar)])) && \
132
155
  (((array_var)[(qvar)]) < (int)(value_ub))) \
133
156
  }
@@ -139,8 +162,8 @@
139
162
  #define array_unchanged_core(qvar, qvar_lb, qvar_ub, array_var) \
140
163
  __CPROVER_forall \
141
164
  { \
142
- unsigned qvar; \
143
- ((qvar_lb) <= (qvar) && (qvar) < (qvar_ub)) ==> \
165
+ uint32_t qvar; \
166
+ ((uint32_t) (qvar_lb) <= (qvar) && (qvar) < (uint32_t) (qvar_ub)) ==> \
144
167
  ((array_var)[(qvar)]) == (old(* (int16_t (*)[(qvar_ub)])(array_var)))[(qvar)] \
145
168
  }
146
169
 
@@ -150,8 +173,8 @@
150
173
  #define array_unchanged_u64_core(qvar, qvar_lb, qvar_ub, array_var) \
151
174
  __CPROVER_forall \
152
175
  { \
153
- unsigned qvar; \
154
- ((qvar_lb) <= (qvar) && (qvar) < (qvar_ub)) ==> \
176
+ uint32_t qvar; \
177
+ ((uint32_t) (qvar_lb) <= (qvar) && (qvar) < (uint32_t) (qvar_ub)) ==> \
155
178
  ((array_var)[(qvar)]) == (old(* (uint64_t (*)[(qvar_ub)])(array_var)))[(qvar)] \
156
179
  }
157
180
 
@@ -24,8 +24,12 @@
24
24
  * this can be overwritten by the user, e.g. for single-CU builds. */
25
25
  #if !defined(MLK_CONFIG_INTERNAL_API_QUALIFIER)
26
26
  #define MLK_INTERNAL_API
27
+ #define MLK_INTERNAL_DATA_DECLARATION extern
28
+ #define MLK_INTERNAL_DATA_DEFINITION
27
29
  #else
28
30
  #define MLK_INTERNAL_API MLK_CONFIG_INTERNAL_API_QUALIFIER
31
+ #define MLK_INTERNAL_DATA_DECLARATION MLK_CONFIG_INTERNAL_API_QUALIFIER
32
+ #define MLK_INTERNAL_DATA_DEFINITION MLK_CONFIG_INTERNAL_API_QUALIFIER
29
33
  #endif
30
34
 
31
35
  #if !defined(MLK_CONFIG_EXTERNAL_API_QUALIFIER)
@@ -218,14 +222,18 @@
218
222
  #if !defined(MLK_CONFIG_CUSTOM_ALLOC_FREE)
219
223
  /* Default: stack allocation */
220
224
 
225
+ /* This is a declaration macro, not an expression macro: T is a type and v is
226
+ * a declarator, neither of which can be wrapped in parentheses. The
227
+ * bugprone-macro-parentheses diagnostic is therefore a false positive here. */
221
228
  #define MLK_ALLOC(v, T, N, context) \
222
229
  MLK_ALIGN T mlk_alloc_##v[N]; \
223
- T *v = mlk_alloc_##v
230
+ T *v = mlk_alloc_##v /* NOLINT(bugprone-macro-parentheses) */
224
231
 
225
- /* TODO: This leads to a circular dependency between common and verify.h
226
- * It just works out before we're at the end of the file, but it's still
227
- * prone to issues in the future. */
228
- #include "verify.h"
232
+ /* The MLK_FREE macro body references mlk_zeroize(), which is declared in
233
+ * verify.h. We deliberately do NOT include verify.h here: doing so would
234
+ * create a circular dependency (verify.h includes common.h), and common.h
235
+ * itself never calls mlk_zeroize() -- only the macro expansion does. Each
236
+ * translation unit that uses MLK_FREE therefore includes verify.h directly. */
229
237
  #define MLK_FREE(v, T, N, context) \
230
238
  do \
231
239
  { \
@@ -261,13 +269,13 @@
261
269
  /****************************** Error codes ***********************************/
262
270
 
263
271
  /* Generic failure condition */
264
- #define MLK_ERR_FAIL -1
272
+ #define MLK_ERR_FAIL (-1)
265
273
  /* An allocation failed. This can only happen if MLK_CONFIG_CUSTOM_ALLOC_FREE
266
274
  * is defined and the provided MLK_CUSTOM_ALLOC can fail. */
267
- #define MLK_ERR_OUT_OF_MEMORY -2
275
+ #define MLK_ERR_OUT_OF_MEMORY (-2)
268
276
  /* An rng failure occured. Might be due to insufficient entropy or
269
277
  * system misconfiguration. */
270
- #define MLK_ERR_RNG_FAIL -3
278
+ #define MLK_ERR_RNG_FAIL (-3)
271
279
 
272
280
  #endif /* !__ASSEMBLER__ */
273
281
 
@@ -32,7 +32,7 @@
32
32
  * - In contrast to the reference implementation, we assume
33
33
  * unsigned canonical coefficients here.
34
34
  * The reference implementation works with coefficients
35
- * in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
35
+ * in the range [-(MLKEM_Q-1), MLKEM_Q-1]. */
36
36
  MLK_STATIC_TESTABLE void mlk_poly_compress_d4_c(
37
37
  uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D4], const mlk_poly *a)
38
38
  __contract__(
@@ -46,14 +46,16 @@ __contract__(
46
46
  mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
47
47
 
48
48
  for (i = 0; i < MLKEM_N / 8; i++)
49
- __loop__(invariant(i <= MLKEM_N / 8))
49
+ __loop__(invariant(i <= MLKEM_N / 8)
50
+ decreases(MLKEM_N / 8 - i))
50
51
  {
51
52
  unsigned j;
52
53
  uint8_t t[8] = {0};
53
54
  for (j = 0; j < 8; j++)
54
55
  __loop__(
55
56
  invariant(i <= MLKEM_N / 8 && j <= 8)
56
- invariant(array_bound(t, 0, j, 0, 16)))
57
+ invariant(array_bound(t, 0, j, 0, 16))
58
+ decreases(8 - j))
57
59
  {
58
60
  t[j] = mlk_scalar_compress_d4(a->coeffs[8 * i + j]);
59
61
  }
@@ -94,7 +96,7 @@ __contract__(
94
96
  * - In contrast to the reference implementation, we assume
95
97
  * unsigned canonical coefficients here.
96
98
  * The reference implementation works with coefficients
97
- * in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
99
+ * in the range [-(MLKEM_Q-1), MLKEM_Q-1]. */
98
100
  MLK_STATIC_TESTABLE void mlk_poly_compress_d10_c(
99
101
  uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D10], const mlk_poly *a)
100
102
  __contract__(
@@ -107,14 +109,16 @@ __contract__(
107
109
  unsigned j;
108
110
  mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
109
111
  for (j = 0; j < MLKEM_N / 4; j++)
110
- __loop__(invariant(j <= MLKEM_N / 4))
112
+ __loop__(invariant(j <= MLKEM_N / 4)
113
+ decreases(MLKEM_N / 4 - j))
111
114
  {
112
115
  unsigned k;
113
116
  uint16_t t[4];
114
117
  for (k = 0; k < 4; k++)
115
118
  __loop__(
116
119
  invariant(k <= 4)
117
- invariant(forall(r, 0, k, t[r] < (1u << 10))))
120
+ invariant(forall(r, 0, k, t[r] < (1u << 10)))
121
+ decreases(4 - k))
118
122
  {
119
123
  t[k] = mlk_scalar_compress_d10(a->coeffs[4 * j + k]);
120
124
  }
@@ -169,7 +173,8 @@ __contract__(
169
173
  for (i = 0; i < MLKEM_N / 2; i++)
170
174
  __loop__(
171
175
  invariant(i <= MLKEM_N / 2)
172
- invariant(array_bound(r->coeffs, 0, 2 * i, 0, MLKEM_Q)))
176
+ invariant(array_bound(r->coeffs, 0, 2 * i, 0, MLKEM_Q))
177
+ decreases(MLKEM_N / 2 - i))
173
178
  {
174
179
  r->coeffs[2 * i + 0] = mlk_scalar_decompress_d4((a[i] >> 0) & 0xF);
175
180
  r->coeffs[2 * i + 1] = mlk_scalar_decompress_d4((a[i] >> 4) & 0xF);
@@ -216,7 +221,8 @@ __contract__(
216
221
  for (j = 0; j < MLKEM_N / 4; j++)
217
222
  __loop__(
218
223
  invariant(j <= MLKEM_N / 4)
219
- invariant(array_bound(r->coeffs, 0, 4 * j, 0, MLKEM_Q)))
224
+ invariant(array_bound(r->coeffs, 0, 4 * j, 0, MLKEM_Q))
225
+ decreases(MLKEM_N / 4 - j))
220
226
  {
221
227
  unsigned k;
222
228
  uint16_t t[4];
@@ -230,7 +236,8 @@ __contract__(
230
236
  for (k = 0; k < 4; k++)
231
237
  __loop__(
232
238
  invariant(k <= 4)
233
- invariant(array_bound(r->coeffs, 0, 4 * j + k, 0, MLKEM_Q)))
239
+ invariant(array_bound(r->coeffs, 0, 4 * j + k, 0, MLKEM_Q))
240
+ decreases(4 - k))
234
241
  {
235
242
  r->coeffs[4 * j + k] = mlk_scalar_decompress_d10(t[k]);
236
243
  }
@@ -269,7 +276,7 @@ __contract__(
269
276
  * - In contrast to the reference implementation, we assume
270
277
  * unsigned canonical coefficients here.
271
278
  * The reference implementation works with coefficients
272
- * in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
279
+ * in the range [-(MLKEM_Q-1), MLKEM_Q-1]. */
273
280
  MLK_STATIC_TESTABLE void mlk_poly_compress_d5_c(
274
281
  uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D5], const mlk_poly *a)
275
282
  __contract__(
@@ -283,14 +290,16 @@ __contract__(
283
290
  mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
284
291
 
285
292
  for (i = 0; i < MLKEM_N / 8; i++)
286
- __loop__(invariant(i <= MLKEM_N / 8))
293
+ __loop__(invariant(i <= MLKEM_N / 8)
294
+ decreases(MLKEM_N / 8 - i))
287
295
  {
288
296
  unsigned j;
289
297
  uint8_t t[8] = {0};
290
298
  for (j = 0; j < 8; j++)
291
299
  __loop__(
292
300
  invariant(i <= MLKEM_N / 8 && j <= 8)
293
- invariant(array_bound(t, 0, j, 0, 32)))
301
+ invariant(array_bound(t, 0, j, 0, 32))
302
+ decreases(8 - j))
294
303
  {
295
304
  t[j] = mlk_scalar_compress_d5(a->coeffs[8 * i + j]);
296
305
  }
@@ -331,7 +340,7 @@ __contract__(
331
340
  * - In contrast to the reference implementation, we assume
332
341
  * unsigned canonical coefficients here.
333
342
  * The reference implementation works with coefficients
334
- * in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
343
+ * in the range [-(MLKEM_Q-1), MLKEM_Q-1]. */
335
344
  MLK_STATIC_TESTABLE void mlk_poly_compress_d11_c(
336
345
  uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D11], const mlk_poly *a)
337
346
  __contract__(
@@ -345,14 +354,16 @@ __contract__(
345
354
  mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
346
355
 
347
356
  for (j = 0; j < MLKEM_N / 8; j++)
348
- __loop__(invariant(j <= MLKEM_N / 8))
357
+ __loop__(invariant(j <= MLKEM_N / 8)
358
+ decreases(MLKEM_N / 8 - j))
349
359
  {
350
360
  unsigned k;
351
361
  uint16_t t[8];
352
362
  for (k = 0; k < 8; k++)
353
363
  __loop__(
354
364
  invariant(k <= 8)
355
- invariant(forall(r, 0, k, t[r] < (1u << 11))))
365
+ invariant(forall(r, 0, k, t[r] < (1u << 11)))
366
+ decreases(8 - k))
356
367
  {
357
368
  t[k] = mlk_scalar_compress_d11(a->coeffs[8 * j + k]);
358
369
  }
@@ -413,7 +424,8 @@ __contract__(
413
424
  for (i = 0; i < MLKEM_N / 8; i++)
414
425
  __loop__(
415
426
  invariant(i <= MLKEM_N / 8)
416
- invariant(array_bound(r->coeffs, 0, 8 * i, 0, MLKEM_Q)))
427
+ invariant(array_bound(r->coeffs, 0, 8 * i, 0, MLKEM_Q))
428
+ decreases(MLKEM_N / 8 - i))
417
429
  {
418
430
  unsigned j;
419
431
  uint8_t t[8];
@@ -441,7 +453,8 @@ __contract__(
441
453
  for (j = 0; j < 8; j++)
442
454
  __loop__(
443
455
  invariant(j <= 8 && i <= MLKEM_N / 8)
444
- invariant(array_bound(r->coeffs, 0, 8 * i + j, 0, MLKEM_Q)))
456
+ invariant(array_bound(r->coeffs, 0, 8 * i + j, 0, MLKEM_Q))
457
+ decreases(8 - j))
445
458
  {
446
459
  r->coeffs[8 * i + j] = mlk_scalar_decompress_d5(t[j]);
447
460
  }
@@ -488,7 +501,8 @@ __contract__(
488
501
  for (j = 0; j < MLKEM_N / 8; j++)
489
502
  __loop__(
490
503
  invariant(j <= MLKEM_N / 8)
491
- invariant(array_bound(r->coeffs, 0, 8 * j, 0, MLKEM_Q)))
504
+ invariant(array_bound(r->coeffs, 0, 8 * j, 0, MLKEM_Q))
505
+ decreases(MLKEM_N / 8 - j))
492
506
  {
493
507
  unsigned k;
494
508
  uint16_t t[8];
@@ -507,7 +521,8 @@ __contract__(
507
521
  for (k = 0; k < 8; k++)
508
522
  __loop__(
509
523
  invariant(k <= 8)
510
- invariant(array_bound(r->coeffs, 0, 8 * j + k, 0, MLKEM_Q)))
524
+ invariant(array_bound(r->coeffs, 0, 8 * j + k, 0, MLKEM_Q))
525
+ decreases(8 - k))
511
526
  {
512
527
  r->coeffs[8 * j + k] = mlk_scalar_decompress_d11(t[k]);
513
528
  }
@@ -545,7 +560,7 @@ __contract__(
545
560
  * - In contrast to the reference implementation, we assume
546
561
  * unsigned canonical coefficients here.
547
562
  * The reference implementation works with coefficients
548
- * in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
563
+ * in the range [-(MLKEM_Q-1), MLKEM_Q-1]. */
549
564
  MLK_STATIC_TESTABLE void mlk_poly_tobytes_c(uint8_t r[MLKEM_POLYBYTES],
550
565
  const mlk_poly *a)
551
566
  __contract__(
@@ -559,7 +574,8 @@ __contract__(
559
574
  mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
560
575
 
561
576
  for (i = 0; i < MLKEM_N / 2; i++)
562
- __loop__(invariant(i <= MLKEM_N / 2))
577
+ __loop__(invariant(i <= MLKEM_N / 2)
578
+ decreases(MLKEM_N / 2 - i))
563
579
  {
564
580
  /* The conversion to uint16_t is safe since we assume that
565
581
  * the coefficients of `a` are non-negative. */
@@ -619,12 +635,18 @@ __contract__(
619
635
  for (i = 0; i < MLKEM_N / 2; i++)
620
636
  __loop__(
621
637
  invariant(i <= MLKEM_N / 2)
622
- invariant(array_bound(r->coeffs, 0, 2 * i, 0, MLKEM_UINT12_LIMIT)))
638
+ invariant(array_bound(r->coeffs, 0, 2 * i, 0, MLKEM_UINT12_LIMIT))
639
+ decreases(MLKEM_N / 2 - i))
623
640
  {
624
641
  const uint8_t t0 = a[3 * i + 0];
625
642
  const uint8_t t1 = a[3 * i + 1];
626
643
  const uint8_t t2 = a[3 * i + 2];
627
- r->coeffs[2 * i + 0] = (int16_t)(t0 | ((t1 << 8) & 0xFFF));
644
+ /* Safety:
645
+ * - The explicit cast to uint16_t ensures that << 8 does
646
+ * not signed-overflow even on a 16-bit system.
647
+ * - The cast to int16_t is safe due to the explicit 0xFFF truncation.
648
+ */
649
+ r->coeffs[2 * i + 0] = (int16_t)(t0 | (((uint16_t)t1 << 8) & 0xFFF));
628
650
  r->coeffs[2 * i + 1] = (int16_t)((t1 >> 4) | (t2 << 4));
629
651
  }
630
652
 
@@ -664,13 +686,15 @@ void mlk_poly_frommsg(mlk_poly *r, const uint8_t msg[MLKEM_INDCPA_MSGBYTES])
664
686
  for (i = 0; i < MLKEM_N / 8; i++)
665
687
  __loop__(
666
688
  invariant(i <= MLKEM_N / 8)
667
- invariant(array_bound(r->coeffs, 0, 8 * i, 0, MLKEM_Q)))
689
+ invariant(array_bound(r->coeffs, 0, 8 * i, 0, MLKEM_Q))
690
+ decreases(MLKEM_N / 8 - i))
668
691
  {
669
692
  unsigned j;
670
693
  for (j = 0; j < 8; j++)
671
694
  __loop__(
672
695
  invariant(i < MLKEM_N / 8 && j <= 8)
673
- invariant(array_bound(r->coeffs, 0, 8 * i + j, 0, MLKEM_Q)))
696
+ invariant(array_bound(r->coeffs, 0, 8 * i + j, 0, MLKEM_Q))
697
+ decreases(8 - j))
674
698
  {
675
699
  /* mlk_ct_sel_int16(MLKEM_Q_HALF, 0, b) is `Decompress_1(b != 0)`
676
700
  * as per @[FIPS203, Eq (4.8)]. */
@@ -687,24 +711,26 @@ void mlk_poly_frommsg(mlk_poly *r, const uint8_t msg[MLKEM_INDCPA_MSGBYTES])
687
711
  * - In contrast to the reference implementation, we assume
688
712
  * unsigned canonical coefficients here.
689
713
  * The reference implementation works with coefficients
690
- * in the range (-MLKEM_Q+1,...,MLKEM_Q-1).
714
+ * in the range [-(MLKEM_Q-1), MLKEM_Q-1].
691
715
  */
692
716
  MLK_INTERNAL_API
693
- void mlk_poly_tomsg(uint8_t msg[MLKEM_INDCPA_MSGBYTES], const mlk_poly *a)
717
+ void mlk_poly_tomsg(uint8_t msg[MLKEM_INDCPA_MSGBYTES], const mlk_poly *r)
694
718
  {
695
719
  unsigned i;
696
- mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
720
+ mlk_assert_bound(r, MLKEM_N, 0, MLKEM_Q);
697
721
 
698
722
  for (i = 0; i < MLKEM_N / 8; i++)
699
- __loop__(invariant(i <= MLKEM_N / 8))
723
+ __loop__(invariant(i <= MLKEM_N / 8)
724
+ decreases(MLKEM_N / 8 - i))
700
725
  {
701
726
  unsigned j;
702
727
  msg[i] = 0;
703
728
  for (j = 0; j < 8; j++)
704
729
  __loop__(
705
- invariant(i <= MLKEM_N / 8 && j <= 8))
730
+ invariant(i <= MLKEM_N / 8 && j <= 8)
731
+ decreases(8 - j))
706
732
  {
707
- uint32_t t = mlk_scalar_compress_d1(a->coeffs[8 * i + j]);
733
+ uint32_t t = mlk_scalar_compress_d1(r->coeffs[8 * i + j]);
708
734
  msg[i] |= (uint8_t)(t << j);
709
735
  }
710
736
  }