Skip to content

Commit

Permalink
CBMC: Add proofs for verify and cmov
Browse files Browse the repository at this point in the history
There is some bitfiddling in cmov and verify that CBMC didn't like:

- Replace `b = -b` by `b = (-b) & 0xFF` to avoid truncation error
- Disable signed-to-unsigned integer conversion check which by default
  rejects conversion of negative integers to unsigned integers.

Signed-off-by: Hanno Becker <[email protected]>
  • Loading branch information
hanno-becker authored and rod-chapman committed Nov 13, 2024
1 parent 11131b9 commit 786ad50
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 12 deletions.
54 changes: 54 additions & 0 deletions cbmc/proofs/cmov/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SPDX-License-Identifier: Apache-2.0

include ../Makefile_params.common

HARNESS_ENTRY = harness
HARNESS_FILE = cmov_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 = cmov

DEFINES +=
INCLUDES +=

REMOVE_FUNCTION_BODY +=
UNWINDSET +=

PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
PROJECT_SOURCES += $(SRCDIR)/mlkem/verify.c

CHECK_FUNCTION_CONTRACTS=$(MLKEM_NAMESPACE)cmov
USE_FUNCTION_CONTRACTS=
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)cmov

# 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 = 8

# 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
3 changes: 3 additions & 0 deletions cbmc/proofs/cmov/cbmc-proof.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: Apache-2.0

# This file marks this directory as containing a CBMC proof.
29 changes: 29 additions & 0 deletions cbmc/proofs/cmov/cmov_harness.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0 AND Apache-2.0

/*
* Insert copyright notice
*/

/**
* @file cmov_harness.c
* @brief Implements the proof harness for cmov function.
*/
#include "verify.h"

/*
* Insert project header files that
* - include the declaration of the function
* - include the types needed to declare function arguments
*/

/**
* @brief Starting point for formal analysis
*
*/
void harness(void) {
uint8_t *x, *y;
size_t len;
uint8_t b;
cmov(x, y, len, b);
}
4 changes: 2 additions & 2 deletions cbmc/proofs/verify/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ USE_DYNAMIC_FRAMES=1

# Disable any setting of EXTERNAL_SAT_SOLVER, and choose SMT backend instead
EXTERNAL_SAT_SOLVER=
CBMCFLAGS=--bitwuzla
CBMCFLAGS=--smt2

FUNCTION_NAME = verify
FUNCTION_NAME = $(MLKEM_NAMESPACE)verify

# 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
Expand Down
4 changes: 2 additions & 2 deletions cbmc/proofs/verify/verify_harness.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

/**
* @file verify_harness.c
* @brief Implements the proof harness for basemul_cached function.
* @brief Implements the proof harness for verify function.
*/
#include "poly.h"
#include "verify.h"

/*
* Insert project header files that
Expand Down
12 changes: 8 additions & 4 deletions mlkem/verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ int verify(const uint8_t *a, const uint8_t *b, const size_t len) {
void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) {
size_t i;

b = -b;
for (i = 0; i < len; i++) {
r[i] ^= b & (r[i] ^ x[i]);
}
b = (-b) & 0xFF;
for (i = 0; i < len; i++) // clang-format off
ASSIGNS(i, OBJECT_UPTO(r, len))
INVARIANT(i <= len)
// clang-format on
{
r[i] ^= b & (r[i] ^ x[i]);
}
}

/*************************************************
Expand Down
10 changes: 6 additions & 4 deletions mlkem/verify.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ ENSURES(RETURN_VALUE == (1 - FORALL(int, i, 0, ((int)len - 1), (a[i] == b[i]))))
* uint8_t b: Condition bit; has to be in {0,1}
**************************************************/
void cmov(uint8_t *r, const uint8_t *x, size_t len,
uint8_t b) // clang-format on
REQUIRES(IS_FRESH(r, len)) REQUIRES(IS_FRESH(x, len))
REQUIRES(b == 0 || b == 1) ASSIGNS(OBJECT_UPTO(r, len));
// clang-format off
uint8_t b) // clang-format off
REQUIRES(IS_FRESH(r, len))
REQUIRES(IS_FRESH(x, len))
REQUIRES(b == 0 || b == 1)
ASSIGNS(OBJECT_UPTO(r, len));
// clang-format on

#define cmov_int16 MLKEM_NAMESPACE(cmov_int16)
/*************************************************
Expand Down

0 comments on commit 786ad50

Please sign in to comment.