Skip to content
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

Let's DOIT: Add support for DOIT-instruction list in (S)CT checkers #736

Closed
wants to merge 7 commits into from

Conversation

J08nY
Copy link
Contributor

@J08nY J08nY commented Feb 23, 2024

This PR will add support for ensuring that secret values only go into guaranteed constant-time instructions (Intel DOITM, ARM DIT).

Currently it does the following:

  • Adds a script for semi-automated extraction of the Intel DOIT/ARM DIT lists. This script checks, in the Intel case, whether the opcodes on the list cover all the instruction encodings of the mnemonic on the list.
  • Adds a CLI option -help-instructions to the compiler that is similar to the -help-instrinsics one but prints all of the instructions for the given architecture that Jasmin understands along with their expanded variants. This is necessary for the automated extraction of the DIT/DOIT instructions that Jasmin supports. Example of output:

VPSUB:VPSUBB
VPSUB:VPSUBD
VPSUB:VPSUBQ
VPSUB:VPSUBW

  • Adds a CLI option -doit to the jazzct tool that switches the CT checker list of constant-time instructions from "all but DIV/MOD" to "only those in the DOIT/DIT" lists. This CLI option also checks that the compiler pass selected is during or after lowering, because the mode otherwise does not make sense.

Which compiler pass to run with

It needs to be done at least after lowering, to have the instructions.

When run right after lowering, the CT checker can have false positives in case of lines like:
if (_LT(of, cf, sf, zf)) {
because it will consider all of the flags, even though the _LT operator only actually considers some.
If run after inline variable propagation this problem disappears, because the expression will be replaced with one that contains only the used flags.

@J08nY J08nY changed the title Let's DOIT Let's DOIT: Add support for DOIT-instruction list in (S)CT checkers Mar 11, 2024
@J08nY
Copy link
Contributor Author

J08nY commented Mar 11, 2024

I have just now noticed #608, which reorganizes the (S)CT checkers and introduces some of the functionality that this PR duplicates, namely the "checkCTafter" CLI option. What is the plan with that PR @bgregoir? Will it get merged soon? Should this get rebased on top of it?

I plan to cleanup the commits in this PR and would like to know which branch to base it on.

Copy link
Contributor

@bgregoir bgregoir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not taken the time to read all of the PR.
But two small remarks:

  • Can you propagate the change also in SCT ?
  • Clearly the changelog needs to be updated.

@bgregoir
Copy link
Contributor

Forgot about the first I was stupid, it is done

Copy link
Contributor

@bgregoir bgregoir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the option checkCTafter should we use it always when we want to do doit?

@bgregoir
Copy link
Contributor

Thank a lot for this PR, I am globally impressed by what you did.
I have some small remarks but maybe I misunderstood some parts.
I think the best will be to discuss of it next week.

@J08nY
Copy link
Contributor Author

J08nY commented Mar 15, 2024

For the option checkCTafter should we use it always when we want to do doit?

Yeah, it does not make sense to use -doit unless you are checking CT after lowering. And as discussed in the PR message, doing it after propagate is even better.

@J08nY J08nY force-pushed the feat/doit branch 5 times, most recently from 30fd559 to 7ac5e20 Compare March 15, 2024 13:35
@J08nY
Copy link
Contributor Author

J08nY commented Mar 15, 2024

I implemented changes based on the review:

  • There is a changelog now.
  • Added a check that gives the user an error if DOIT is run without specifying a (S)CT checking pass that is not after lowering.
  • Added is_doit_asm_extra that tests extra ops for being constructed out of DOIT instructions.
  • Made the DOIT lists to be explicit pattern matches and removed the _ -> false.

One thing that needs to be done (and I do not know how to do it) is to properly print the ARM instructions in the -help-instructions. The x86_64 variant of the code should be cleaned up as well. The intended format of the output is as I described in the PR description:

VPSUB:VPSUBB
VPSUB:VPSUBD
VPSUB:VPSUBQ
VPSUB:VPSUBW

@J08nY
Copy link
Contributor Author

J08nY commented May 8, 2024

I rebased this branch on top of current main. That means that now the -doit option is added to the jazzct binary.

compiler/CCT/fail/strict.jazz Show resolved Hide resolved
@@ -15,6 +15,12 @@ bin = ./scripts/check-cct
okdirs = !CCT/success
kodirs = !CCT/fail

[test-CCT-DOIT]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add also a SCT DOIT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, let me add that.

(when the `-doit` flag is used) check that secrets are only used with
guaranteed constant time instructions (DOIT for Intel, DIT for ARM). This option
only makes sense when done after the lowering compiler pass, which can be ensured
with the new `-after` option.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for -doit, did we have a default pass ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by a default pass? There are two ways I guess:

  • Passing the -doit option also sets the compiler pass to be after inline propagation. If someone also uses the -after option they get an error? Or maybe they get an error only if the pass is before lowering?
  • Passing the -doit option does nothing to the compiler pass set, it needs to be set using the -after option and that will check that the set pass is after lowering. This is currently implemented (and I like it more, but I am open to suggestions).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more in favor of the first one, with
the solution "Or maybe they get an error only if the pass is before lowering?". I think the user don't need
to know the name of the pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, makes sense.

Copy link
Contributor

@bgregoir bgregoir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added some extra small comment. Excepted those I think we will be ok.

(when the `-doit` flag is used) check that secrets are only used with
guaranteed constant time instructions (DOIT for Intel, DIT for ARM). This option
only makes sense when done after the lowering compiler pass, which can be ensured
with the new `-after` option.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more in favor of the first one, with
the solution "Or maybe they get an error only if the pass is before lowering?". I think the user don't need
to know the name of the pass.

@@ -1,8 +1,9 @@
fn add_H_L_L(#secret reg u64 x, #public reg u64 ya) -> #public reg u64 {
export fn add_H_L_L(#secret reg u64 x, #public reg u64 ya) -> #public reg u64 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why you have change all the tests.
What is the motivation of adding the export.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If they are not marked export they are not present at the later compiler passes where DOIT checking happens :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then those programs are not suited for testing the new functionality.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, AFAIK the export does not change anything about them with regards to the CT checking (the ordinary tests would have caught that) so I believe these can be reused for DOIT checking. They should be reused to see that unless specific non-DOIT instructions are used DOIT checking is the same as CT checking.

This brings me to a broader point that DOIT-specific tests should be added, which I will work on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you manually inspect the error messages of the CT checker before and after your change to validate that they are still the same? Do you expect the reviewers of your PR to do this boring work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect the tests (and some understanding of what the export keyword does) to ensure that. Nevertheless I just manually checked and there is no change in the ordinary CT checker output.

compiler/CCT/fail/strict.jazz Show resolved Hide resolved
@@ -172,7 +172,7 @@ let pp_kind fmt k =
if k = Flexible then Format.fprintf fmt "#%s " (string_of_lvl_kind k)

let pp_arg fmt (x, (k, lvl)) =
Format.fprintf fmt "%a%a %a" pp_kind k Lvl.pp lvl (Printer.pp_var ~debug:false) x
Format.fprintf fmt "%a%a %a" pp_kind k Lvl.pp lvl (Printer.pp_var ~debug:!Glob_options.debug) x
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be not the correct fix.
Debug may print many other infos that are usually used
to debug the compiler.
For doit, I am agree that it is important to print the info
(it is done after lower spill), name clashes can occur. But either replace this by just a true or a boolean
depending on the pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, if this is set depending on the pass then the pass would need to be passed through to the checker. I think this will be quite cumbersome.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, fixing this is non trivial and mostly unrelated to this PR. Therefore please:

  1. open an issue
  2. drop this commit from this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: #810.

Adds a CCT-DOIT test group that contains the normal CCT tests
in the success condition and the failure condition as well as
DOIT-specific tests in the failure condition. The DOIT-specific
tests use the two non-DOIT instructions ROL and XCHG.

Reusing the CCT tests required making their main functions
"export" to make sure they are kept at the later compiler passes
where DOIT checking needs to be done.
@vbgl vbgl marked this pull request as draft May 28, 2024 04:41
@vbgl vbgl mentioned this pull request May 28, 2024
@vbgl
Copy link
Member

vbgl commented May 28, 2024

I’ve taken to PR #811 some changes from this PR. Notable changes are that for armv7, instructions LDR, STR, and MOVT have been marked as secure. The rationale for memory accesses is that the documentation explicitly mentions that timing may only depend on the address (which is generically handled by the checker otherwise) and not on the exchanged data. For MOVT, the guess is that this instruction is not listed as a secure instruction of armv8 because it is not an instruction of armv8 in the first place.

@vbgl
Copy link
Member

vbgl commented May 28, 2024

I believe that all the tooling proposed in this PR, namely data extraction from manufacturer’s websites and data extraction from Jasmin, may be moved to a different repository (e.g., attached to a publication related this work).

@vbgl
Copy link
Member

vbgl commented May 28, 2024

Future steps might be:

  • move the DOIT data into the instruction descriptors;
  • prove that pseudo-instructions that are marked DOIT are indeed implemented using DOIT instructions only;
  • implement an independent auditing tool to validate that instructions that are marked secure in the Jasmin implementation are indeed secure according to the manufacturer’s documentation.

@vbgl
Copy link
Member

vbgl commented Jun 24, 2024

Now that PR #736 has been merged, I suggest to close this one.

@vbgl vbgl closed this Jun 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants