Skip to content

Commit 55c610c

Browse files
committed
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 e6d49d4 commit 55c610c

File tree

7 files changed

+242
-0
lines changed

7 files changed

+242
-0
lines changed

mldsa/poly.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,30 @@ __contract__(
425425
ensures(array_abs_bound(r3->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
426426
);
427427

428+
#define mld_poly_uniform_eta MLD_NAMESPACE_KL(poly_uniform_eta)
429+
/*************************************************
430+
* Name: mld_poly_uniform_eta
431+
*
432+
* Description: Sample polynomial with uniformly random coefficients
433+
* in [-MLDSA_ETA,MLDSA_ETA] by performing rejection sampling on
434+
* the output stream from SHAKE256(seed|nonce)
435+
*
436+
* Arguments: - mld_poly *r: pointer to output polynomial
437+
* - const uint8_t seed[]: byte array with seed of length
438+
* MLDSA_CRHBYTES
439+
* - uint8_t nonce: nonce
440+
**************************************************/
441+
MLD_INTERNAL_API
442+
void mld_poly_uniform_eta(mld_poly *r, const uint8_t seed[MLDSA_CRHBYTES],
443+
uint8_t nonce)
444+
__contract__(
445+
requires(memory_no_alias(r, sizeof(mld_poly)))
446+
requires(memory_no_alias(seed, MLDSA_CRHBYTES))
447+
assigns(memory_slice(r, sizeof(mld_poly)))
448+
ensures(array_abs_bound(r->coeffs, 0, MLDSA_N, MLDSA_ETA + 1))
449+
);
450+
451+
428452
#define mld_poly_uniform_gamma1 MLD_NAMESPACE_KL(poly_uniform_gamma1)
429453
/*************************************************
430454
* Name: mld_poly_uniform_gamma1

mldsa/poly_kl.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ __contract__(
318318
return ctr;
319319
}
320320

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

405462

406463
#define POLY_UNIFORM_GAMMA1_NBLOCKS \

mldsa/sign.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,20 @@ __contract__(
119119
)
120120
{
121121
/* Sample short vectors s1 and s2 */
122+
#if defined(MLD_CONFIG_SERIAL_FIPS202_ONLY)
123+
int i;
124+
uint16_t nonce = 0;
125+
/* Safety: The nonces are at most 14 (MLDSA_L + MLDSA_K - 1), and, hence, the
126+
* casts are safe. */
127+
for (i = 0; i < MLDSA_L; i++)
128+
{
129+
mld_poly_uniform_eta(&s1->vec[i], seed, (uint8_t)(nonce + i));
130+
}
131+
for (i = 0; i < MLDSA_K; i++)
132+
{
133+
mld_poly_uniform_eta(&s2->vec[i], seed, (uint8_t)(nonce + MLDSA_L + i));
134+
}
135+
#else /* MLD_CONFIG_SERIAL_FIPS202_ONLY */
122136
#if MLD_CONFIG_PARAMETER_SET == 44
123137
mld_poly_uniform_eta_4x(&s1->vec[0], &s1->vec[1], &s1->vec[2], &s1->vec[3],
124138
seed, 0, 1, 2, 3);
@@ -143,6 +157,7 @@ __contract__(
143157
mld_poly_uniform_eta_4x(&s2->vec[4], &s2->vec[5], &s2->vec[6], &s2->vec[7],
144158
seed, 11, 12, 13, 14);
145159
#endif /* MLD_CONFIG_PARAMETER_SET == 87 */
160+
#endif /* !MLD_CONFIG_SERIAL_FIPS202_ONLY */
146161
}
147162

148163
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)