diff --git a/cbmc/proofs/indcpa_enc/Makefile b/cbmc/proofs/indcpa_enc/Makefile new file mode 100644 index 000000000..6006a5f3b --- /dev/null +++ b/cbmc/proofs/indcpa_enc/Makefile @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: Apache-2.0 + +include ../Makefile_params.common + +HARNESS_ENTRY = harness +HARNESS_FILE = indcpa_enc_harness + +# This should be a unique identifier for this proof, and will appear on the +# Litani dashboard. It can be human-readable and contain spaces if you wish. +PROOF_UID = indcpa_enc + +DEFINES += +INCLUDES += + +REMOVE_FUNCTION_BODY += +UNWINDSET += + +PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c +PROJECT_SOURCES += $(SRCDIR)/mlkem/indcpa.c + +CHECK_FUNCTION_CONTRACTS=$(MLKEM_NAMESPACE)indcpa_enc + +USED_FUNCTIONS = poly_frommsg +USED_FUNCTIONS += gen_matrix +ifeq ($(MLKEM_K),2) +USED_FUNCTIONS += poly_getnoise_eta1122_4x +USED_FUNCTIONS += poly_getnoise_eta2 +else ifeq ($(MLKEM_K),3) +USED_FUNCTIONS += poly_getnoise_eta1_4x +else ifeq ($(MLKEM_K),4) +USED_FUNCTIONS += poly_getnoise_eta1_4x +USED_FUNCTIONS += poly_getnoise_eta2 +endif + +USED_FUNCTIONS += polyvec_ntt +USED_FUNCTIONS += polyvec_mulcache_compute +USED_FUNCTIONS += polyvec_basemul_acc_montgomery_cached +USED_FUNCTIONS += polyvec_invntt_tomont +USED_FUNCTIONS += poly_invntt_tomont +USED_FUNCTIONS += polyvec_add +USED_FUNCTIONS += poly_add +USED_FUNCTIONS += polyvec_reduce +USED_FUNCTIONS += poly_reduce +USED_FUNCTIONS += polyvec_compress +USED_FUNCTIONS += poly_compress + +USE_FUNCTION_CONTRACTS=unpack_pk matvec_mul $(addprefix $(MLKEM_NAMESPACE),$(USED_FUNCTIONS)) +APPLY_LOOP_CONTRACTS=on +USE_DYNAMIC_FRAMES=1 + +# Disable any setting of EXTERNAL_SAT_SOLVER, and choose SMT backend instead +EXTERNAL_SAT_SOLVER= +CBMCFLAGS=--smt2 + +FUNCTION_NAME = $(MLKEM_NAMESPACE)indcpa_enc + +# If this proof is found to consume huge amounts of RAM, you can set the +# EXPENSIVE variable. With new enough versions of the proof tools, this will +# restrict the number of EXPENSIVE CBMC jobs running at once. See the +# documentation in Makefile.common under the "Job Pools" heading for details. +# EXPENSIVE = true + +# This function is large enough to need... +CBMC_OBJECT_BITS = 10 + +# If you require access to a file-local ("static") function or object to conduct +# your proof, set the following (and do not include the original source file +# ("mlkem/poly.c") in PROJECT_SOURCES). +# REWRITTEN_SOURCES = $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i +# include ../Makefile.common +# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_SOURCE = $(SRCDIR)/mlkem/poly.c +# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_FUNCTIONS = foo bar +# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_OBJECTS = baz +# Care is required with variables on the left-hand side: REWRITTEN_SOURCES must +# be set before including Makefile.common, but any use of variables on the +# left-hand side requires those variables to be defined. Hence, _SOURCE, +# _FUNCTIONS, _OBJECTS is set after including Makefile.common. + +include ../Makefile.common diff --git a/cbmc/proofs/indcpa_enc/cbmc-proof.txt b/cbmc/proofs/indcpa_enc/cbmc-proof.txt new file mode 100644 index 000000000..3d1913ebf --- /dev/null +++ b/cbmc/proofs/indcpa_enc/cbmc-proof.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +# This file marks this directory as containing a CBMC proof. diff --git a/cbmc/proofs/indcpa_enc/indcpa_enc_harness.c b/cbmc/proofs/indcpa_enc/indcpa_enc_harness.c new file mode 100644 index 000000000..b05cd9fd8 --- /dev/null +++ b/cbmc/proofs/indcpa_enc/indcpa_enc_harness.c @@ -0,0 +1,28 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT-0 + +/* + * Insert copyright notice + */ + +/** + * @file indcpa_keypair_derand_harness.c + * @brief Implements the proof harness for indcpa_keypair_derand function. + */ + +/* + * Insert project header files that + * - include the declaration of the function + * - include the types needed to declare function arguments + */ +#include +#include + +/** + * @brief Starting point for formal analysis + * + */ +void harness(void) { + uint8_t *a, *b, *c, *d; + indcpa_enc(a, b, c, d); +} diff --git a/mlkem/indcpa.h b/mlkem/indcpa.h index ec4e98976..b7e277154 100644 --- a/mlkem/indcpa.h +++ b/mlkem/indcpa.h @@ -36,7 +36,13 @@ void indcpa_keypair_derand( void indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES], const uint8_t m[MLKEM_INDCPA_MSGBYTES], const uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES], - const uint8_t coins[MLKEM_SYMBYTES]); + const uint8_t coins[MLKEM_SYMBYTES]) // clang-format off + REQUIRES(IS_FRESH(c, MLKEM_INDCPA_BYTES)) + REQUIRES(IS_FRESH(m, MLKEM_INDCPA_MSGBYTES)) + REQUIRES(IS_FRESH(pk, MLKEM_INDCPA_PUBLICKEYBYTES)) + REQUIRES(IS_FRESH(coins, MLKEM_SYMBYTES)) + ASSIGNS(OBJECT_WHOLE(c)); +// clang-format on #define indcpa_dec MLKEM_NAMESPACE(indcpa_dec) void indcpa_dec(uint8_t m[MLKEM_INDCPA_MSGBYTES], diff --git a/mlkem/poly.h b/mlkem/poly.h index f773548b9..1f075f288 100644 --- a/mlkem/poly.h +++ b/mlkem/poly.h @@ -517,10 +517,9 @@ void poly_getnoise_eta1122_4x(poly *r0, poly *r1, poly *r2, poly *r3, const uint8_t seed[MLKEM_SYMBYTES], uint8_t nonce0, uint8_t nonce1, uint8_t nonce2, uint8_t nonce3) // clang-format off -REQUIRES(IS_FRESH(r0, sizeof(poly))) -REQUIRES(IS_FRESH(r1, sizeof(poly))) -REQUIRES(IS_FRESH(r2, sizeof(poly))) -REQUIRES(IS_FRESH(r3, sizeof(poly))) +REQUIRES( /* r0, r1 consecutive, r2, r3 consecutive */ + (IS_FRESH(r0, 2 * sizeof(poly)) && IS_FRESH(r2, 2 * sizeof(poly)) && + r1 == r0 + 1 && r3 == r2 + 1 && !SAME_OBJECT(r0, r2))) REQUIRES(IS_FRESH(seed, MLKEM_SYMBYTES)) ASSIGNS(OBJECT_WHOLE(r0), OBJECT_WHOLE(r1), OBJECT_WHOLE(r2), OBJECT_WHOLE(r3)) ENSURES( \