-
Notifications
You must be signed in to change notification settings - Fork 0
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
feat: make labels erasable #54
Conversation
(asking @qaphla for review since we discussed that in Stuttgart) |
Some preliminary thoughts, before I go through it more deeply:
I'll go over it more carefully soon, and also see if I come up with any better comments on these points, but I think only the second one ( |
Thank you for your comments! About About About About doing the same thing for |
On I think On three-valued logic: On usages: Overall:
|
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.
See discussion for more details.
- Minor complaint about
get_label
returningpublic
for ill-formed bytes (to become an issue) - Discussion sparked about three-valued logic/monotone functions for a "weak" version of
get_label
that avoids the need for a special case for ill-formed bytes. - I look forward to seeing usages get similar treatment.
Thanks! We could make an interface file like val any_label: label and use that in |
Now asking the thoughts of @cwaldm and @fabian-hk: do you think the impact on the proofs is fine? Especially considering this brings other benefits (such as a nice equational theory on labels done in #56 which avoid having to deal with |
I think that makes it sufficiently less suspicious for now (though I do still want to think more about if there's a way to cleanly work with but hide options) --- in particular, because it prevents anyone from unintentionally using that label, regardless of what it is. I'm a bit uncertain if |
I have done that in the In #55 I did something a bit fancier, so that reasoning on |
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.
Looks good to me.
I think unknown_label
should be sufficiently self-documenting in get_label
, especially since one can easily follow back to the fsti file for more information.
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've looked over the updates, and this (still) looks fine to me, though of course feedback from others would also be welcome.
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.
Looks fine to me as well!
This PR adds the
[@@erasable]
to thelabel
type…… and updates the rest of the code to reflect this change :)
Because
label
s are erasable, they can't appear in theRand
constructor ofbytes
on which we want decidable equality. As a consequence, we now have a challenge to define theget_label
function on theRand
constructor that previously contained the label, and that now only contain the time at which the randomness was generated (which correspond to aRandGen
event in the trace, that do contain the label).There are two approaches to this problem:
get_label
as-is, but labels become more complicated with indirections (for labels ofRand
)trace
to the arguments ofget_label
and keep labels as-is (without indirections)Now that
get_label
depends on the trace, we need new properties such as "the output ofget_label
dosen't change when the trace grows".Here we get to a technical difficulty: what does
get_label
answer on aRand
constructor that do not correspond to aRandGen
event in the trace? For example, if thetime
of random generation is in the future (with respect to that trace)? Then surely the output ofget_label
may change when the random bytestring is actually generated.To deal with this scenario, we define a new well-formed check (
bytes_well_formed
) that checks whether allRand
s inside abytes
correspond to aRandGen
event in the trace. This allows us to define the theoremget_label_later
statingNow the question: how do we prove the precondition
bytes_well_formed tr1 b
? In most cases, we can rely on the theoremThe only place where we can't rely on
bytes_invariant
is when we define thebytes_invariant
, namely in thecrypto_predicates
, more precisely in thepred_later
lemmas. In that case, all cryptographic functions come with lemmas stating how they preserved the well-formedness, although I think in most scenarios we will just need the ones onsplit
andconcat
that will be handled by Comparse (as it is done in the NSL example).Although it looks like a big change, the examples were easy to update and proofs mostly didn't break.
Digression on
has_label
I spent quite some time thinking about a third option, which is using a predicate
val has_label: trace -> bytes -> label -> prop
(which would be monotonic in the trace)It looks convenient because we could say that a malformed
bytes
has no labels.However, the difficulty is the following: how do we express that the plaintext must flow to the key (e.g. in AEAD)?
Before, we wrote
Now we could write
However if
key
is malformed, the precondition is never realized (becausekey
has no label) so this would be true,but that might become false when the trace grows (and
key
becomes well-formed).So instead we could write
But we need to prove that
key
has a label, which brings back the well-formedness problem.Hence it seems that we have to deal with well-formedness when using
has_label
too, so I don't think it's worth doing (as it would be strictly more annoying to use than what is in this PR).