-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cryptol support for crux-mir-comp #1313
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a super nice feature enhancement. As mentioned in a couple of comments, I wonder whether some of the What4 <-> SAWCore code could go into the saw-core-what4
package (probably as a future PR, and maybe along with some similar code from the saw-script
package).
where | ||
sc = msb ^. msbSharedContext | ||
eval :: forall tp. W4.Expr t tp -> IO SAW.Term | ||
eval = msb ^. msbEval | ||
|
||
-- | Find assertions of the form `var == expr` that are suitable for | ||
-- performing substitutions, and separate them from the list of assertions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's perhaps interesting to note that the first version of SAWScript separated equality assertions from other assertions in the MethodSpec datatype (by having different user-visible primitives for stating them) for performance reasons. I wonder whether we should return to that.
goField (OptField shp) sv = W4.justPartExpr sym <$> go shp sv | ||
|
||
-- | Build a bitvector from a vector of bits. The length of the vector is | ||
-- required to match `w`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder whether this should be moved into What4. It seems like it could be useful in other contexts.
|
||
|
||
exprToTerm :: forall sym t st fs tp m. | ||
(IsSymInterface sym, sym ~ W4.ExprBuilder t st fs, MonadIO m, MonadFail m) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and a lot of the other, similar functions in this module seem like they could also be very broadly useful. It might even be worth having a What4-SAWCore integration package that included all these conversions back and forth. Centralizing that could make it easier to identify how to do the conversions as sparingly and effectively as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, the existing saw-core-what4
package might be a good place for these sorts of functions.
The major change in this branch is adding support for calling Cryptol functions from Rust in
crux-mir-comp
. Symbolic tests can use thecryptol!
macro to declare Rust bindings for Cryptol functions. Example:With these declarations, calling
message_schedule
invokes the Cryptol functionmessageSchedule_Common
(of type[16][32] -> [64][32]
) from the modulePrimitive::Keyless::Hash::SHA256
, and callingmessage_schedule_one
invokes the Cryptol lambda expression given as a string (which usessigma_0
andsigma_1
imported from the same module).Bindings are typechecked on first use. Cryptol functions can use bit, array, and tuple types; the Rust signature must use the corresponding
bool
, array, and tuple types. For convenience, bitvectors such as the Cryptol type[32]
can match not only the Rust type[bool; 32]
but alsou32
andi32
.This branch also includes several smaller changes that were necessary to get compositional verification against Cryptol specs working in practice (specifically, on
ring
's SHA256 implementation):Add a workaround for imperfect what4 -> saw-core -> what4 round-tripping. Defining a MethodSpec in
crux-mir-comp
involves converting what4 exprs from the Crucible state into saw-core terms to be stored in the MethodSpec. Applying the MethodSpec override then converts those saw-core terms back to what4. In some cases, this what4 -> saw-core -> what4 round trip can produce an equivalent but non-identical expression, which causes problems for compositional crypto verification, as it requires certain pairs of subexpressions to be identical in order to get decent solver performance. So this branch introduces a new function,fn munge<T>(x: T) -> T
, which converts every what4 expr inx
to saw-core and back. This operation seems to be idempotent, so it's safe to use even on expressions where some parts were already round-tripped due to calling a MethodSpec override, and I was able to get the Ring SHA256 verification to pass by wrapping both the "real" and Cryptol/spec sides of each equality in calls tomunge
.Equalities in postconditions are now converted into substitutions when possible. With our current approach to compositional verification, the overrides derived from equivalence tests typically look like this:
It seems neither Yices nor Z3 will reliably substitute for
y
(effectively converting the override toreturn cryptol_func(x);
). So we now recognize postconditions of this form and do the substitution explicitly in the override. (Specifically, we check forvar == expr
at the what4 level, so it works even for types like(u32, u32)
that involve multiple what4 variables/expressions.)Add support for Rust's
#[repr(transparent)]
attribute. This attribute can be applied to a newtype (a struct with only one non-zero-sized field) to ensure that the newtype has the same representation in memory as the type that it wraps. With this change,#[repr(transparent)]
guarantees that the newtype and the inner type have the same Crucible representation, enabling some no-optransmute
s and pointer casts that were previously forbidden.#[repr(transparent)]
newtypes are used inGenericArray
andcore::num::Wrapping
, which appear in some crypto code.Add support for slice (
&[T]
) arguments in MethodSpecs. These are simply treated as a pair(&T, usize)
of a reference and a length.This unfortunately makes for MethodSpecs that are quite strict by default: if the user's test case invokes
f(&xs[1..3])
, then the MethodSpec derived from that test case will require the argument slice to have length exactly 2 and to have at least one accessible element at offset -1. But relaxing these restrictions would require weakening the preconditions of the orginal test case written by the user, which doesn't seem feasible.Add overrides for additional Rust intrinsics (unchecked arithmetic and
rotate_left
/right
).The related changes to ordinary
crux-mir
are in GaloisInc/crucible#749