Skip to content

Commit 0beea41

Browse files
mkannwischerrod-chapman
authored andcommitted
Serial FIPS202 2/3: Adapt mld_sample_s1_s2
This commit changes mld_sample_s1_s2 to use poly_uniform_eta only in case MLD_CONFIG_SERIAL_FIPS202_ONLY is set. poly_uniform_eta was previously removed because we don't need it in case batching is enabled. It is re-added here. A new CBMC proof for poly_uniform_eta is added. An additional CBMC proof for sample_s1_s2 with MLD_CONFIG_SERIAL_FIPS202_ONLY set is added. Signed-off-by: Matthias J. Kannwischer <[email protected]>
1 parent 562f8b7 commit 0beea41

File tree

7 files changed

+242
-0
lines changed

7 files changed

+242
-0
lines changed

mldsa/src/poly_kl.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ __contract__(
324324
return ctr;
325325
}
326326

327+
#if !defined(MLD_CONFIG_SERIAL_FIPS202_ONLY)
327328
MLD_INTERNAL_API
328329
void mld_poly_uniform_eta_4x(mld_poly *r0, mld_poly *r1, mld_poly *r2,
329330
mld_poly *r3, const uint8_t seed[MLDSA_CRHBYTES],
@@ -407,6 +408,62 @@ void mld_poly_uniform_eta_4x(mld_poly *r0, mld_poly *r1, mld_poly *r2,
407408
mld_zeroize(buf, sizeof(buf));
408409
mld_zeroize(extseed, sizeof(extseed));
409410
}
411+
#else /* !MLD_CONFIG_SERIAL_FIPS202_ONLY */
412+
MLD_INTERNAL_API
413+
void mld_poly_uniform_eta(mld_poly *r, const uint8_t seed[MLDSA_CRHBYTES],
414+
uint8_t nonce)
415+
{
416+
/* Temporary buffer for XOF output before rejection sampling */
417+
MLD_ALIGN uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES];
418+
MLD_ALIGN uint8_t extseed[MLDSA_CRHBYTES + 2];
419+
420+
/* Tracks the number of coefficients we have already sampled */
421+
unsigned ctr;
422+
mld_xof256_ctx state;
423+
unsigned buflen;
424+
425+
mld_memcpy(extseed, seed, MLDSA_CRHBYTES);
426+
extseed[MLDSA_CRHBYTES] = nonce;
427+
extseed[MLDSA_CRHBYTES + 1] = 0;
428+
429+
mld_xof256_init(&state);
430+
mld_xof256_absorb_once(&state, extseed, MLDSA_CRHBYTES + 2);
431+
432+
/*
433+
* Initially, squeeze heuristic number of POLY_UNIFORM_ETA_NBLOCKS.
434+
* This should generate the coefficients with high probability.
435+
*/
436+
mld_xof256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state);
437+
buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES;
438+
439+
ctr = mld_rej_eta(r->coeffs, MLDSA_N, 0, buf, buflen);
440+
441+
/*
442+
* So long as not all entries have been generated, squeeze
443+
* one more block a time until we're done.
444+
*/
445+
buflen = STREAM256_BLOCKBYTES;
446+
while (ctr < MLDSA_N)
447+
__loop__(
448+
assigns(ctr, memory_slice(&state, sizeof(mld_xof256_ctx)),
449+
memory_slice(buf, STREAM256_BLOCKBYTES), memory_slice(r, sizeof(mld_poly)))
450+
invariant(ctr <= MLDSA_N)
451+
invariant(state.pos <= SHAKE256_RATE)
452+
invariant(array_abs_bound(r->coeffs, 0, ctr, MLDSA_ETA + 1)))
453+
{
454+
mld_xof256_squeezeblocks(buf, 1, &state);
455+
ctr = mld_rej_eta(r->coeffs, MLDSA_N, ctr, buf, buflen);
456+
}
457+
458+
mld_xof256_release(&state);
459+
460+
mld_assert_abs_bound(r->coeffs, MLDSA_N, MLDSA_ETA + 1);
461+
462+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
463+
mld_zeroize(buf, sizeof(buf));
464+
mld_zeroize(extseed, sizeof(extseed));
465+
}
466+
#endif /* MLD_CONFIG_SERIAL_FIPS202_ONLY */
410467

411468
#define POLY_UNIFORM_GAMMA1_NBLOCKS \
412469
((MLDSA_POLYZ_PACKEDBYTES + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES)

mldsa/src/poly_kl.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,30 @@ __contract__(
162162
);
163163

164164
#if MLD_CONFIG_PARAMETER_SET == 65
165+
#define mld_poly_uniform_eta MLD_NAMESPACE_KL(poly_uniform_eta)
166+
/*************************************************
167+
* Name: mld_poly_uniform_eta
168+
*
169+
* Description: Sample polynomial with uniformly random coefficients
170+
* in [-MLDSA_ETA,MLDSA_ETA] by performing rejection sampling on
171+
* the output stream from SHAKE256(seed|nonce)
172+
*
173+
* Arguments: - mld_poly *r: pointer to output polynomial
174+
* - const uint8_t seed[]: byte array with seed of length
175+
* MLDSA_CRHBYTES
176+
* - uint8_t nonce: nonce
177+
**************************************************/
178+
MLD_INTERNAL_API
179+
void mld_poly_uniform_eta(mld_poly *r, const uint8_t seed[MLDSA_CRHBYTES],
180+
uint8_t nonce)
181+
__contract__(
182+
requires(memory_no_alias(r, sizeof(mld_poly)))
183+
requires(memory_no_alias(seed, MLDSA_CRHBYTES))
184+
assigns(memory_slice(r, sizeof(mld_poly)))
185+
ensures(array_abs_bound(r->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
186+
);
187+
188+
165189
#define mld_poly_uniform_gamma1 MLD_NAMESPACE_KL(poly_uniform_gamma1)
166190
/*************************************************
167191
* Name: mld_poly_uniform_gamma1

mldsa/src/sign.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,20 @@ __contract__(
131131
)
132132
{
133133
/* Sample short vectors s1 and s2 */
134+
#if defined(MLD_CONFIG_SERIAL_FIPS202_ONLY)
135+
int i;
136+
uint16_t nonce = 0;
137+
/* Safety: The nonces are at most 14 (MLDSA_L + MLDSA_K - 1), and, hence, the
138+
* casts are safe. */
139+
for (i = 0; i < MLDSA_L; i++)
140+
{
141+
mld_poly_uniform_eta(&s1->vec[i], seed, (uint8_t)(nonce + i));
142+
}
143+
for (i = 0; i < MLDSA_K; i++)
144+
{
145+
mld_poly_uniform_eta(&s2->vec[i], seed, (uint8_t)(nonce + MLDSA_L + i));
146+
}
147+
#else /* MLD_CONFIG_SERIAL_FIPS202_ONLY */
134148
#if MLD_CONFIG_PARAMETER_SET == 44
135149
mld_poly_uniform_eta_4x(&s1->vec[0], &s1->vec[1], &s1->vec[2], &s1->vec[3],
136150
seed, 0, 1, 2, 3);
@@ -155,6 +169,7 @@ __contract__(
155169
mld_poly_uniform_eta_4x(&s2->vec[4], &s2->vec[5], &s2->vec[6], &s2->vec[7],
156170
seed, 11, 12, 13, 14);
157171
#endif /* MLD_CONFIG_PARAMETER_SET == 87 */
172+
#endif /* !MLD_CONFIG_SERIAL_FIPS202_ONLY */
158173
}
159174

160175
MLD_MUST_CHECK_RETURN_VALUE
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright (c) The mldsa-native project authors
2+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
3+
4+
include ../Makefile_params.common
5+
6+
HARNESS_ENTRY = harness
7+
HARNESS_FILE = poly_uniform_eta_harness
8+
9+
# This should be a unique identifier for this proof, and will appear on the
10+
# Litani dashboard. It can be human-readable and contain spaces if you wish.
11+
PROOF_UID = poly_uniform_eta
12+
13+
DEFINES += -DMLD_CONFIG_SERIAL_FIPS202_ONLY
14+
INCLUDES +=
15+
16+
REMOVE_FUNCTION_BODY +=
17+
UNWINDSET +=
18+
19+
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
20+
PROJECT_SOURCES += $(SRCDIR)/mldsa/poly_kl.c
21+
22+
CHECK_FUNCTION_CONTRACTS=$(MLD_NAMESPACE)poly_uniform_eta
23+
USE_FUNCTION_CONTRACTS=$(FIPS202_NAMESPACE)shake256_init
24+
USE_FUNCTION_CONTRACTS+=$(FIPS202_NAMESPACE)shake256_absorb
25+
USE_FUNCTION_CONTRACTS+=$(FIPS202_NAMESPACE)shake256_finalize
26+
USE_FUNCTION_CONTRACTS+=$(FIPS202_NAMESPACE)shake256_squeeze
27+
USE_FUNCTION_CONTRACTS+=mld_rej_eta
28+
USE_FUNCTION_CONTRACTS+=$(FIPS202_NAMESPACE)shake256_release
29+
USE_FUNCTION_CONTRACTS+=mld_zeroize
30+
APPLY_LOOP_CONTRACTS=on
31+
USE_DYNAMIC_FRAMES=1
32+
33+
# Disable any setting of EXTERNAL_SAT_SOLVER, and choose SMT backend instead
34+
EXTERNAL_SAT_SOLVER=
35+
CBMCFLAGS=--smt2
36+
37+
FUNCTION_NAME = poly_uniform_eta
38+
39+
# If this proof is found to consume huge amounts of RAM, you can set the
40+
# EXPENSIVE variable. With new enough versions of the proof tools, this will
41+
# restrict the number of EXPENSIVE CBMC jobs running at once. See the
42+
# documentation in Makefile.common under the "Job Pools" heading for details.
43+
# EXPENSIVE = true
44+
45+
# This function is large enough to need...
46+
CBMC_OBJECT_BITS = 9
47+
48+
# If you require access to a file-local ("static") function or object to conduct
49+
# your proof, set the following (and do not include the original source file
50+
# ("mldsa/poly.c") in PROJECT_SOURCES).
51+
# REWRITTEN_SOURCES = $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i
52+
# include ../Makefile.common
53+
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_SOURCE = $(SRCDIR)/mldsa/poly.c
54+
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_FUNCTIONS = foo bar
55+
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_OBJECTS = baz
56+
# Care is required with variables on the left-hand side: REWRITTEN_SOURCES must
57+
# be set before including Makefile.common, but any use of variables on the
58+
# left-hand side requires those variables to be defined. Hence, _SOURCE,
59+
# _FUNCTIONS, _OBJECTS is set after including Makefile.common.
60+
61+
include ../Makefile.common
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) The mldsa-native project authors
2+
// SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
3+
4+
#include "poly.h"
5+
6+
void harness(void)
7+
{
8+
mld_poly *r0;
9+
const uint8_t *seed;
10+
uint8_t n0;
11+
12+
mld_poly_uniform_eta(r0, seed, n0);
13+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Copyright (c) The mldsa-native project authors
2+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
3+
4+
include ../Makefile_params.common
5+
6+
HARNESS_ENTRY = harness
7+
HARNESS_FILE = sample_s1_s2_harness
8+
9+
# This should be a unique identifier for this proof, and will appear on the
10+
# Litani dashboard. It can be human-readable and contain spaces if you wish.
11+
PROOF_UID = mld_sample_s1_s2_serial
12+
13+
DEFINES += -DMLD_CONFIG_SERIAL_FIPS202_ONLY
14+
INCLUDES +=
15+
16+
REMOVE_FUNCTION_BODY +=
17+
UNWINDSET += mld_sample_s1_s2.0:7 # Largest value of MLDSA_L
18+
UNWINDSET += mld_sample_s1_s2.1:8 # Largest value of MLDSA_K
19+
20+
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
21+
PROJECT_SOURCES += $(SRCDIR)/mldsa/sign.c
22+
23+
CHECK_FUNCTION_CONTRACTS=mld_sample_s1_s2
24+
USE_FUNCTION_CONTRACTS=$(MLD_NAMESPACE)poly_uniform_eta
25+
APPLY_LOOP_CONTRACTS=on
26+
USE_DYNAMIC_FRAMES=1
27+
28+
# Disable any setting of EXTERNAL_SAT_SOLVER, and choose SMT backend instead
29+
EXTERNAL_SAT_SOLVER=
30+
CBMCFLAGS=--smt2
31+
32+
FUNCTION_NAME = mld_sample_s1_s2_serial
33+
34+
# If this proof is found to consume huge amounts of RAM, you can set the
35+
# EXPENSIVE variable. With new enough versions of the proof tools, this will
36+
# restrict the number of EXPENSIVE CBMC jobs running at once. See the
37+
# documentation in Makefile.common under the "Job Pools" heading for details.
38+
# EXPENSIVE = true
39+
40+
# This function is large enough to need...
41+
CBMC_OBJECT_BITS = 10
42+
43+
# If you require access to a file-local ("static") function or object to conduct
44+
# your proof, set the following (and do not include the original source file
45+
# ("mldsa/poly.c") in PROJECT_SOURCES).
46+
# REWRITTEN_SOURCES = $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i
47+
# include ../Makefile.common
48+
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_SOURCE = $(SRCDIR)/mldsa/poly.c
49+
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_FUNCTIONS = foo bar
50+
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_OBJECTS = baz
51+
# Care is required with variables on the left-hand side: REWRITTEN_SOURCES must
52+
# be set before including Makefile.common, but any use of variables on the
53+
# left-hand side requires those variables to be defined. Hence, _SOURCE,
54+
# _FUNCTIONS, _OBJECTS is set after including Makefile.common.
55+
56+
include ../Makefile.common
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) The mldsa-native project authors
2+
// SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
3+
4+
#include "sign.h"
5+
6+
static void mld_sample_s1_s2(mld_polyvecl *s1, mld_polyveck *s2,
7+
const uint8_t seed[MLDSA_CRHBYTES]);
8+
9+
void harness(void)
10+
{
11+
mld_polyvecl *s1;
12+
mld_polyveck *s2;
13+
uint8_t *seed;
14+
15+
mld_sample_s1_s2(s1, s2, seed);
16+
}

0 commit comments

Comments
 (0)