Skip to content

Commit f9f6373

Browse files
committed
Add CBMC starter kit and initial (trivial) sha2_256_init proof
Setup heavily based on mlkem-native. Also see https://github.com/model-checking/cbmc-starter-kit Signed-off-by: Matthias J. Kannwischer <[email protected]>
1 parent 7afba09 commit f9f6373

File tree

11 files changed

+2037
-1
lines changed

11 files changed

+2037
-1
lines changed

cbmc.h

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Copyright (c) The mlkem-native project authors
3+
* Copyright (c) The slhdsa-native project authors
4+
* SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
5+
*/
6+
7+
#ifndef SLH_CBMC_H
8+
#define SLH_CBMC_H
9+
/***************************************************
10+
* Basic replacements for __CPROVER_XXX contracts
11+
***************************************************/
12+
13+
#ifndef CBMC
14+
15+
#define __contract__(x)
16+
#define __loop__(x)
17+
18+
#else /* !CBMC */
19+
20+
#define __contract__(x) x
21+
#define __loop__(x) x
22+
23+
/* https://diffblue.github.io/cbmc/contracts-assigns.html */
24+
#define assigns(...) __CPROVER_assigns(__VA_ARGS__)
25+
26+
/* https://diffblue.github.io/cbmc/contracts-requires-ensures.html */
27+
#define requires(...) __CPROVER_requires(__VA_ARGS__)
28+
#define ensures(...) __CPROVER_ensures(__VA_ARGS__)
29+
/* https://diffblue.github.io/cbmc/contracts-loops.html */
30+
#define invariant(...) __CPROVER_loop_invariant(__VA_ARGS__)
31+
#define decreases(...) __CPROVER_decreases(__VA_ARGS__)
32+
/* cassert to avoid confusion with in-built assert */
33+
#define cassert(x) __CPROVER_assert(x, "cbmc assertion failed")
34+
#define assume(...) __CPROVER_assume(__VA_ARGS__)
35+
36+
/***************************************************
37+
* Macros for "expression" forms that may appear
38+
* _inside_ top-level contracts.
39+
***************************************************/
40+
41+
/*
42+
* function return value - useful inside ensures
43+
* https://diffblue.github.io/cbmc/contracts-functions.html
44+
*/
45+
#define return_value (__CPROVER_return_value)
46+
47+
/*
48+
* assigns l-value targets
49+
* https://diffblue.github.io/cbmc/contracts-assigns.html
50+
*/
51+
#define object_whole(...) __CPROVER_object_whole(__VA_ARGS__)
52+
#define memory_slice(...) __CPROVER_object_upto(__VA_ARGS__)
53+
#define same_object(...) __CPROVER_same_object(__VA_ARGS__)
54+
55+
/*
56+
* Pointer-related predicates
57+
* https://diffblue.github.io/cbmc/contracts-memory-predicates.html
58+
*/
59+
#define memory_no_alias(...) __CPROVER_is_fresh(__VA_ARGS__)
60+
#define readable(...) __CPROVER_r_ok(__VA_ARGS__)
61+
#define writeable(...) __CPROVER_w_ok(__VA_ARGS__)
62+
63+
/*
64+
* History variables
65+
* https://diffblue.github.io/cbmc/contracts-history-variables.html
66+
*/
67+
#define old(...) __CPROVER_old(__VA_ARGS__)
68+
#define loop_entry(...) __CPROVER_loop_entry(__VA_ARGS__)
69+
70+
/*
71+
* Quantifiers
72+
* Note that the range on qvar is _exclusive_ between qvar_lb .. qvar_ub
73+
* https://diffblue.github.io/cbmc/contracts-quantifiers.html
74+
*/
75+
76+
/*
77+
* Prevent clang-format from corrupting CBMC's special ==> operator
78+
*/
79+
/* clang-format off */
80+
#define forall(qvar, qvar_lb, qvar_ub, predicate) \
81+
__CPROVER_forall \
82+
{ \
83+
unsigned qvar; \
84+
((qvar_lb) <= (qvar) && (qvar) < (qvar_ub)) ==> (predicate) \
85+
}
86+
87+
#define EXISTS(qvar, qvar_lb, qvar_ub, predicate) \
88+
__CPROVER_exists \
89+
{ \
90+
unsigned qvar; \
91+
((qvar_lb) <= (qvar) && (qvar) < (qvar_ub)) && (predicate) \
92+
}
93+
/* clang-format on */
94+
95+
/***************************************************
96+
* Convenience macros for common contract patterns
97+
***************************************************/
98+
99+
/*
100+
* Boolean-value predidate that asserts that "all values of array_var are in
101+
* range value_lb (inclusive) .. value_ub (exclusive)"
102+
* Example:
103+
* array_bound(a->coeffs, 0, SLHEM_N, 0, SLHEM_Q)
104+
* expands to
105+
* __CPROVER_forall { int k; (0 <= k && k <= SLHEM_N-1) ==> (
106+
* 0 <= a->coeffs[k]) && a->coeffs[k] < SLHEM_Q)) }
107+
*/
108+
109+
/*
110+
* Prevent clang-format from corrupting CBMC's special ==> operator
111+
*/
112+
/* clang-format off */
113+
#define CBMC_CONCAT_(left, right) left##right
114+
#define CBMC_CONCAT(left, right) CBMC_CONCAT_(left, right)
115+
116+
#define array_bound_core(qvar, qvar_lb, qvar_ub, array_var, \
117+
value_lb, value_ub) \
118+
__CPROVER_forall \
119+
{ \
120+
unsigned qvar; \
121+
((qvar_lb) <= (qvar) && (qvar) < (qvar_ub)) ==> \
122+
(((int)(value_lb) <= ((array_var)[(qvar)])) && \
123+
(((array_var)[(qvar)]) < (int)(value_ub))) \
124+
}
125+
126+
#define array_bound(array_var, qvar_lb, qvar_ub, value_lb, value_ub) \
127+
array_bound_core(CBMC_CONCAT(_cbmc_idx, __LINE__), (qvar_lb), \
128+
(qvar_ub), (array_var), (value_lb), (value_ub))
129+
/* clang-format on */
130+
131+
/* Wrapper around array_bound operating on absolute values.
132+
*
133+
* The absolute value bound `k` is exclusive.
134+
*
135+
* Note that since the lower bound in array_bound is inclusive, we have to
136+
* raise it by 1 here.
137+
*/
138+
#define array_abs_bound(arr, lb, ub, k) \
139+
array_bound((arr), (lb), (ub), -((int)(k)) + 1, (k))
140+
141+
#endif /* CBMC */
142+
143+
#endif /* !SLH_CBMC_H */

proofs/cbmc/.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
2+
3+
# Emitted when running CBMC proofs
4+
**/logs
5+
**/gotos
6+
**/report
7+
**/html
8+
output
9+
10+
# Emitted by CBMC Viewer
11+
TAGS-*
12+
13+
# Emitted by litani
14+
.ninja_deps
15+
.ninja_log
16+
.litani_cache_dir
17+
18+
# These files should be overwritten whenever prepare.py runs
19+
cbmc-batch.yaml
20+
21+
__pycache__/

0 commit comments

Comments
 (0)