-
Notifications
You must be signed in to change notification settings - Fork 19
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
Improvements to formal verification of P-384 #141
Improvements to formal verification of P-384 #141
Conversation
…on. Working on improving the organization.
…erification into p384_validate_2
…erification into p384_validate_2
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 reviewed the SAW proof part of this PR.
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 looked through the files in Coq/EC/
and the README and didn't find anything problematic -- the Coq changes are largely refactoring.
Some more high-level comments:
-
I left a couple minor comments about documenting assumptions in the proofs when a comment wasn't readily available. For easier review in the future, you might consider adding a special comment string (e.g. "ASSUMPTION") to assumptions like
Variable
andHypothesis
.
If you're in the mood for some hacking, you could even set up GitHub CI to check that all assumptions are documented, and nothing is admitted. We do something sort of similar in our Rust code, where we check that any function that can panic is prefixed by a comment with the string "PANIC SAFETY". -
How are the new table validation functions actually run? I see that they're assumed to pass in the proofs, but I didn't notice them being extracted anywhere.
# First, apply some patches (TODO: remove them)... | ||
# Start by patching in the constant validation tests and executing them | ||
apply_patch "p384_validate" |
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.
Out of curiosity: what are these patches for? Are they changes that need to be contributed back to the SAW tool? Are you doing any verification pre-patching, or is all testing/verification done on the patched code?
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.
The patches are mostly used to make trivial modifications to the code (that we believe produce semantically equivalent code) to work around tool limitations or otherwise allow the formal verification to work. Most patches are used to mark functions as noinline
so they will not be inlined when compiling from C to LLVM, and so we can prove them correct and re-use these proofs when functions are called. All verification is done after patching the code.
This particular patch adds in the constant verification code. This test code uses symbols that are not visible outside the p384.c
file, so the test code needs to be inside this file. The simple solution is to patch it in, and then invoke the test function from the existing test suite.
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.
To answer your question about how the test is executed: it is patched in to the test suite by the patch on line 20 of this file, and then then the entire test suite is executed on line 30.
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.
But the code patched in here is C code, right? How does that relate to the Coq validation functions?
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.
The patched in C functions are verified against a Cryptol spec using SAW. This is done in EC_P384_validate.saw
, and the Cryptol spec was added to EC_mul.cry
(e.g. validate_base_table
). The Cryptol spec is converted to Gallina functions with the same name, and we prove the required correctness properties of these functions in Coq. We also assume that validate_base_table
was executed on the pre-computed table on line 648 of EcEqProof.v
, and this assumption is justified by the fact that we executed a C function that is proven to behave in the same way as this function.
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.
Got it, thanks for the clarification!
Coq/EC/ECEqProof.v
Outdated
Variable felem_from_bytes : Vector.t bool 384 -> F. | ||
Variable felem_to_bytes : F -> Vector.t bool 384. | ||
Hypothesis felem_from_to_bytes_inv : forall x, felem_from_bytes (felem_to_bytes x) = x. | ||
Hypothesis felem_to_from_bytes_inv : forall x, felem_to_bytes (felem_from_bytes x) = x. |
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.
Add explanation for these variables and hypotheses
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.
Added comments. I also removed the second Hypothesis
because it is not necessary, and also probably not true for the conversion routines supplied by fiat-crypto and s2n-bignum.
Variable F_order_correct : nat -> Prop. | ||
Context `{F_FiniteField : @FiniteField F_order_correct F Feq _ _ _ _ _ _ _ _ F_field}. | ||
Hypothesis p384_field_order_correct : F_order_correct p384_field_order. |
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.
Add explanation for these variables and hypotheses
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.
Added a comment.
Theorem sub_eq_mono : forall x1 x2 y1 y2, | ||
x1 = x2 -> | ||
y1 = y2 -> | ||
(x1 - y1)%nat = (x2 - y2)%nat. |
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.
Several of the lemmas in this file seem like they could be discharged by builtin tactics like lia
. Are you separating them out for performance reasons?
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.
Lemmas like this are only used to help me structure proofs of other facts. In the case of this lemma, if I have a goal like x1 - y1 = x2 - y2
, I can apply this theorem to replace it with goals x1 = x2
and y1 = y2
. I could accomplish the same thing with Ltac or rewriting (in some cases), but applying a theorem is often simpler.
Variable point_double : point -> point. | ||
Variable point_add : bool -> point -> point -> point. | ||
Variable sign_extend_16_64 : (bitvector 16) -> (bitvector 64). | ||
Variable point_id_to_limb : (bitvector 16) -> (bitvector 64). | ||
Variable F_cmovznz : (bitvector 64) -> F -> F -> F. | ||
Variable select_point_loop_body : (bitvector 64) -> point -> (bitvector 64) -> point -> point. | ||
Definition double_add_body_abstract := @double_add_body_abstract Fopp F_cmovznz select_point_loop_body | ||
point_add point_double sign_extend_16_64. | ||
Definition select_point_abstract := @select_point_abstract select_point_loop_body. | ||
|
||
Hypothesis F_cmovznz_equiv : forall x y z, | ||
F_cmovznz x y z = if (bvEq _ x (intToBv 64 0)) then y else z. | ||
|
||
Hypothesis select_point_loop_body_equiv : forall w x y z, | ||
select_point_loop_body w x y z = | ||
if (bvEq _ y w) then z else x. | ||
|
||
Hypothesis point_add_jac_eq : forall (a b: Curve.point) a' b', | ||
jac_eq (fromPoint a) (seqToProd a') -> | ||
jac_eq (fromPoint b) (seqToProd b') -> | ||
jac_eq (fromPoint (Curve.add a b)) (seqToProd (point_add false a' b')). | ||
|
||
Hypothesis point_add_mixed_eq : forall (a b:Curve.point) a' b', | ||
nth_order b' two_lt_three = Fone -> | ||
jac_eq (fromPoint a) (seqToProd a') -> | ||
jac_eq (fromPoint b) (seqToProd b') -> | ||
jac_eq (fromPoint (Curve.add a b)) (seqToProd (point_add true a' b')). | ||
|
||
Hypothesis point_double_minus_3_jac_eq : forall (p:Curve.point) p', | ||
jac_eq (fromPoint p) (seqToProd p') -> | ||
jac_eq (fromPoint (Curve.double_minus_3 p)) (seqToProd (point_double p')). | ||
|
||
Hypothesis sbvToInt_sign_extend_16_64_equiv : forall x, | ||
sbvToInt _ (sign_extend_16_64 x) = sbvToInt _ x. |
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.
Add explanation for these variables and hypotheses
(Similar comment for other uses of Hypothesis
in this file, but wanted to avoid spamming comments.)
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 added some comments and re-organized the file a bit. Many of these variables/hypotheses are internal to the proof, and they are replaced with concrete terms and proofs in ECEqProof.v. Let me know if more documentation is needed to make all this clear.
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.
Thanks, the new re-org and comments are useful.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
This PR has the following significant improvements to the formal verification of P-384
The README file was updated to remove the two significant caveats associated with the changes above. I also added two new caveats:
There are also significant organizational changes to the Coq proof in this PR. These changes should improve the overall organization, and they were helpful in isolating Coq performance issues that arise from operating on actual values.