Skip to content

Commit 32c1493

Browse files
committed
Switch mlk_polyvec and mlk_polymat to struct wrappers
- Change mlk_polyvec back to struct `{ mlk_poly vec[MLKEM_K]; }` - Change mlk_polymat to struct `{ mlk_polyvec vec[MLKEM_K]; }` - Update all function signatures to use pointer style - Fix all implementations to use struct member access - Update tests, benchmarks, and CBMC harnesses - Add consistent const annotations Somewhat surprisingly and dissatisfyingly, I could not salvage the CBMC proof for the 'monolithic' polymat_permute_bitrev_to_custom_native but had to break it in two functions. It would be good to resolve this as the split causes a lot of code-overhead for an entirely trivial function. Signed-off-by: Hanno Becker <[email protected]>
1 parent 854f0bc commit 32c1493

File tree

28 files changed

+330
-223
lines changed

28 files changed

+330
-223
lines changed

mlkem/src/indcpa.c

Lines changed: 115 additions & 78 deletions
Large diffs are not rendered by default.

mlkem/src/indcpa.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@
3939
*
4040
**************************************************/
4141
MLK_INTERNAL_API
42-
void mlk_gen_matrix(mlk_polymat a, const uint8_t seed[MLKEM_SYMBYTES],
42+
void mlk_gen_matrix(mlk_polymat *a, const uint8_t seed[MLKEM_SYMBYTES],
4343
int transposed)
4444
__contract__(
4545
requires(memory_no_alias(a, sizeof(mlk_polymat)))
4646
requires(memory_no_alias(seed, MLKEM_SYMBYTES))
4747
requires(transposed == 0 || transposed == 1)
4848
assigns(object_whole(a))
49-
ensures(forall(x, 0, MLKEM_K * MLKEM_K,
50-
array_bound(a[x].coeffs, 0, MLKEM_N, 0, MLKEM_Q)))
49+
ensures(forall(x, 0, MLKEM_K, forall(y, 0, MLKEM_K,
50+
array_bound(a->vec[x].vec[y].coeffs, 0, MLKEM_N, 0, MLKEM_Q))))
5151
);
5252

5353
#define mlk_indcpa_keypair_derand MLK_NAMESPACE_K(indcpa_keypair_derand)

mlkem/src/kem.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ int crypto_kem_check_pk(const uint8_t pk[MLKEM_INDCCA_PUBLICKEYBYTES])
4646
mlk_polyvec p;
4747
uint8_t p_reencoded[MLKEM_POLYVECBYTES];
4848

49-
mlk_polyvec_frombytes(p, pk);
50-
mlk_polyvec_reduce(p);
51-
mlk_polyvec_tobytes(p_reencoded, p);
49+
mlk_polyvec_frombytes(&p, pk);
50+
mlk_polyvec_reduce(&p);
51+
mlk_polyvec_tobytes(p_reencoded, &p);
5252

5353
/* We use a constant-time memcmp here to avoid having to
5454
* declassify the PK before the PCT has succeeded. */

mlkem/src/poly_k.c

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,29 @@
4747
* in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
4848
MLK_INTERNAL_API
4949
void mlk_polyvec_compress_du(uint8_t r[MLKEM_POLYVECCOMPRESSEDBYTES_DU],
50-
const mlk_polyvec a)
50+
const mlk_polyvec *a)
5151
{
5252
unsigned i;
53-
mlk_assert_bound_2d(a, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
53+
mlk_assert_bound_2d(a->vec, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
5454

5555
for (i = 0; i < MLKEM_K; i++)
5656
{
57-
mlk_poly_compress_du(r + i * MLKEM_POLYCOMPRESSEDBYTES_DU, &a[i]);
57+
mlk_poly_compress_du(r + i * MLKEM_POLYCOMPRESSEDBYTES_DU, &a->vec[i]);
5858
}
5959
}
6060

6161
/* Reference: `polyvec_decompress()` in the reference implementation @[REF]. */
6262
MLK_INTERNAL_API
63-
void mlk_polyvec_decompress_du(mlk_polyvec r,
63+
void mlk_polyvec_decompress_du(mlk_polyvec *r,
6464
const uint8_t a[MLKEM_POLYVECCOMPRESSEDBYTES_DU])
6565
{
6666
unsigned i;
6767
for (i = 0; i < MLKEM_K; i++)
6868
{
69-
mlk_poly_decompress_du(&r[i], a + i * MLKEM_POLYCOMPRESSEDBYTES_DU);
69+
mlk_poly_decompress_du(&r->vec[i], a + i * MLKEM_POLYCOMPRESSEDBYTES_DU);
7070
}
7171

72-
mlk_assert_bound_2d(r, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
72+
mlk_assert_bound_2d(r->vec, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
7373
}
7474

7575
/* Reference: `polyvec_tobytes()` in the reference implementation @[REF].
@@ -78,45 +78,45 @@ void mlk_polyvec_decompress_du(mlk_polyvec r,
7878
* The reference implementation works with coefficients
7979
* in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
8080
MLK_INTERNAL_API
81-
void mlk_polyvec_tobytes(uint8_t r[MLKEM_POLYVECBYTES], const mlk_polyvec a)
81+
void mlk_polyvec_tobytes(uint8_t r[MLKEM_POLYVECBYTES], const mlk_polyvec *a)
8282
{
8383
unsigned i;
84-
mlk_assert_bound_2d(a, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
84+
mlk_assert_bound_2d(a->vec, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
8585

8686
for (i = 0; i < MLKEM_K; i++)
8787
__loop__(
8888
assigns(i, object_whole(r))
8989
invariant(i <= MLKEM_K)
9090
)
9191
{
92-
mlk_poly_tobytes(&r[i * MLKEM_POLYBYTES], &a[i]);
92+
mlk_poly_tobytes(&r[i * MLKEM_POLYBYTES], &a->vec[i]);
9393
}
9494
}
9595

9696
/* Reference: `polyvec_frombytes()` in the reference implementation @[REF]. */
9797
MLK_INTERNAL_API
98-
void mlk_polyvec_frombytes(mlk_polyvec r, const uint8_t a[MLKEM_POLYVECBYTES])
98+
void mlk_polyvec_frombytes(mlk_polyvec *r, const uint8_t a[MLKEM_POLYVECBYTES])
9999
{
100100
unsigned i;
101101
for (i = 0; i < MLKEM_K; i++)
102102
{
103-
mlk_poly_frombytes(&r[i], a + i * MLKEM_POLYBYTES);
103+
mlk_poly_frombytes(&r->vec[i], a + i * MLKEM_POLYBYTES);
104104
}
105105

106-
mlk_assert_bound_2d(r, MLKEM_K, MLKEM_N, 0, MLKEM_UINT12_LIMIT);
106+
mlk_assert_bound_2d(r->vec, MLKEM_K, MLKEM_N, 0, MLKEM_UINT12_LIMIT);
107107
}
108108

109109
/* Reference: `polyvec_ntt()` in the reference implementation @[REF]. */
110110
MLK_INTERNAL_API
111-
void mlk_polyvec_ntt(mlk_polyvec r)
111+
void mlk_polyvec_ntt(mlk_polyvec *r)
112112
{
113113
unsigned i;
114114
for (i = 0; i < MLKEM_K; i++)
115115
{
116-
mlk_poly_ntt(&r[i]);
116+
mlk_poly_ntt(&r->vec[i]);
117117
}
118118

119-
mlk_assert_abs_bound_2d(r, MLKEM_K, MLKEM_N, MLK_NTT_BOUND);
119+
mlk_assert_abs_bound_2d(r->vec, MLKEM_K, MLKEM_N, MLK_NTT_BOUND);
120120
}
121121

122122
/* Reference: `polyvec_invntt_tomont()` in the reference implementation @[REF].
@@ -125,15 +125,15 @@ void mlk_polyvec_ntt(mlk_polyvec r)
125125
* the end. This allows us to drop a call to `poly_reduce()`
126126
* from the base multiplication. */
127127
MLK_INTERNAL_API
128-
void mlk_polyvec_invntt_tomont(mlk_polyvec r)
128+
void mlk_polyvec_invntt_tomont(mlk_polyvec *r)
129129
{
130130
unsigned i;
131131
for (i = 0; i < MLKEM_K; i++)
132132
{
133-
mlk_poly_invntt_tomont(&r[i]);
133+
mlk_poly_invntt_tomont(&r->vec[i]);
134134
}
135135

136-
mlk_assert_abs_bound_2d(r, MLKEM_K, MLKEM_N, MLK_INVNTT_BOUND);
136+
mlk_assert_abs_bound_2d(r->vec, MLKEM_K, MLKEM_N, MLK_INVNTT_BOUND);
137137
}
138138

139139
/* Reference: `polyvec_basemul_acc_montgomery()` in the
@@ -148,20 +148,20 @@ void mlk_polyvec_invntt_tomont(mlk_polyvec r)
148148
* more modular reductions since it reduces after every modular
149149
* multiplication. */
150150
MLK_STATIC_TESTABLE void mlk_polyvec_basemul_acc_montgomery_cached_c(
151-
mlk_poly *r, const mlk_polyvec a, const mlk_polyvec b,
152-
const mlk_polyvec_mulcache b_cache)
151+
mlk_poly *r, const mlk_polyvec *a, const mlk_polyvec *b,
152+
const mlk_polyvec_mulcache *b_cache)
153153
__contract__(
154154
requires(memory_no_alias(r, sizeof(mlk_poly)))
155155
requires(memory_no_alias(a, sizeof(mlk_polyvec)))
156156
requires(memory_no_alias(b, sizeof(mlk_polyvec)))
157157
requires(memory_no_alias(b_cache, sizeof(mlk_polyvec_mulcache)))
158158
requires(forall(k1, 0, MLKEM_K,
159-
array_bound(a[k1].coeffs, 0, MLKEM_N, 0, MLKEM_UINT12_LIMIT)))
159+
array_bound(a->vec[k1].coeffs, 0, MLKEM_N, 0, MLKEM_UINT12_LIMIT)))
160160
assigns(object_whole(r))
161161
)
162162
{
163163
unsigned i;
164-
mlk_assert_bound_2d(a, MLKEM_K, MLKEM_N, 0, MLKEM_UINT12_LIMIT);
164+
mlk_assert_bound_2d(a->vec, MLKEM_K, MLKEM_N, 0, MLKEM_UINT12_LIMIT);
165165

166166
for (i = 0; i < MLKEM_N / 2; i++)
167167
__loop__(invariant(i <= MLKEM_N / 2))
@@ -176,10 +176,10 @@ __contract__(
176176
t[1] <= ((int32_t) k * 2 * MLKEM_UINT12_LIMIT * 32768) &&
177177
t[1] >= - ((int32_t) k * 2 * MLKEM_UINT12_LIMIT * 32768)))
178178
{
179-
t[0] += (int32_t)a[k].coeffs[2 * i + 1] * b_cache[k].coeffs[i];
180-
t[0] += (int32_t)a[k].coeffs[2 * i] * b[k].coeffs[2 * i];
181-
t[1] += (int32_t)a[k].coeffs[2 * i] * b[k].coeffs[2 * i + 1];
182-
t[1] += (int32_t)a[k].coeffs[2 * i + 1] * b[k].coeffs[2 * i];
179+
t[0] += (int32_t)a->vec[k].coeffs[2 * i + 1] * b_cache->vec[k].coeffs[i];
180+
t[0] += (int32_t)a->vec[k].coeffs[2 * i] * b->vec[k].coeffs[2 * i];
181+
t[1] += (int32_t)a->vec[k].coeffs[2 * i] * b->vec[k].coeffs[2 * i + 1];
182+
t[1] += (int32_t)a->vec[k].coeffs[2 * i + 1] * b->vec[k].coeffs[2 * i];
183183
}
184184
r->coeffs[2 * i + 0] = mlk_montgomery_reduce(t[0]);
185185
r->coeffs[2 * i + 1] = mlk_montgomery_reduce(t[1]);
@@ -188,8 +188,8 @@ __contract__(
188188

189189
MLK_INTERNAL_API
190190
void mlk_polyvec_basemul_acc_montgomery_cached(
191-
mlk_poly *r, const mlk_polyvec a, const mlk_polyvec b,
192-
const mlk_polyvec_mulcache b_cache)
191+
mlk_poly *r, const mlk_polyvec *a, const mlk_polyvec *b,
192+
const mlk_polyvec_mulcache *b_cache)
193193
{
194194
#if defined(MLK_USE_NATIVE_POLYVEC_BASEMUL_ACC_MONTGOMERY_CACHED)
195195
{
@@ -225,12 +225,12 @@ void mlk_polyvec_basemul_acc_montgomery_cached(
225225
* multiplication cache ('mulcache'). This idea originates
226226
* from @[NeonNTT] and is used at the C level here. */
227227
MLK_INTERNAL_API
228-
void mlk_polyvec_mulcache_compute(mlk_polyvec_mulcache x, const mlk_polyvec a)
228+
void mlk_polyvec_mulcache_compute(mlk_polyvec_mulcache *x, const mlk_polyvec *a)
229229
{
230230
unsigned i;
231231
for (i = 0; i < MLKEM_K; i++)
232232
{
233-
mlk_poly_mulcache_compute(&x[i], &a[i]);
233+
mlk_poly_mulcache_compute(&x->vec[i], &a->vec[i]);
234234
}
235235
}
236236

@@ -242,41 +242,41 @@ void mlk_polyvec_mulcache_compute(mlk_polyvec_mulcache x, const mlk_polyvec a)
242242
* This conditional addition is then dropped from all
243243
* polynomial compression functions instead (see `compress.c`). */
244244
MLK_INTERNAL_API
245-
void mlk_polyvec_reduce(mlk_polyvec r)
245+
void mlk_polyvec_reduce(mlk_polyvec *r)
246246
{
247247
unsigned i;
248248
for (i = 0; i < MLKEM_K; i++)
249249
{
250-
mlk_poly_reduce(&r[i]);
250+
mlk_poly_reduce(&r->vec[i]);
251251
}
252252

253-
mlk_assert_bound_2d(r, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
253+
mlk_assert_bound_2d(r->vec, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
254254
}
255255

256256
/* Reference: `polyvec_add()` in the reference implementation @[REF].
257257
* - We use destructive version (output=first input) to avoid
258258
* reasoning about aliasing in the CBMC specification */
259259
MLK_INTERNAL_API
260-
void mlk_polyvec_add(mlk_polyvec r, const mlk_polyvec b)
260+
void mlk_polyvec_add(mlk_polyvec *r, const mlk_polyvec *b)
261261
{
262262
unsigned i;
263263
for (i = 0; i < MLKEM_K; i++)
264264
{
265-
mlk_poly_add(&r[i], &b[i]);
265+
mlk_poly_add(&r->vec[i], &b->vec[i]);
266266
}
267267
}
268268

269269
/* Reference: `polyvec_tomont()` in the reference implementation @[REF]. */
270270
MLK_INTERNAL_API
271-
void mlk_polyvec_tomont(mlk_polyvec r)
271+
void mlk_polyvec_tomont(mlk_polyvec *r)
272272
{
273273
unsigned i;
274274
for (i = 0; i < MLKEM_K; i++)
275275
{
276-
mlk_poly_tomont(&r[i]);
276+
mlk_poly_tomont(&r->vec[i]);
277277
}
278278

279-
mlk_assert_abs_bound_2d(r, MLKEM_K, MLKEM_N, MLKEM_Q);
279+
mlk_assert_abs_bound_2d(r->vec, MLKEM_K, MLKEM_N, MLKEM_Q);
280280
}
281281

282282

0 commit comments

Comments
 (0)