This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] Mask instructions in Zkt as constant-time
Needs ReviewPublic

Authored by wangpc on Jul 19 2023, 3:08 AM.

Details

Summary

We use one bit in TSFlags to indicate that this instruction has
data-independent execution time property (constant-time) as required
in Zkt extension.

This property may help to verify whether a function is constant-time.

(Though there are limited usages currently, I think this will be
helpful to crypto libraries).

Diff Detail

Unit TestsFailed

Event Timeline

wangpc created this revision.Jul 19 2023, 3:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2023, 3:08 AM
wangpc requested review of this revision.Jul 19 2023, 3:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2023, 3:08 AM
asb added a comment.Jul 19 2023, 5:48 AM

Interesting idea. Some initial thoughts:

  • The HINT instructions are not included in the constant time guarantee, and this approach doesn't account for that
  • A different name is probably need, as these instructions are only known to be constant time if zkt is enabled, and we'll need something similar for zvkt.

I'll put this on the agenda for the RISC-V LLVM sync-up call tomorrow.

craig.topper added inline comments.Jul 19 2023, 8:39 AM
llvm/lib/Target/RISCV/RISCVInstrFormats.td
211

zkt -> Zkt

In order for this to work, the loop over the buffer to encrypt has to be a separate piece of code? Since the branch instructions aren't constant time.

This patch needs a test that shows the warning fires for a non-constant time instruction.

wangpc added a comment.EditedJul 19 2023, 10:46 AM

In order for this to work, the loop over the buffer to encrypt has to be a separate piece of code? Since the branch instructions aren't constant time.

This patch needs a test that shows the warning fires for a non-constant time instruction.

I'm imagining something like this:

__attribute__((constant_time))
void aes128_encrypt(char block_to_encrypt[16], __attribute__((secret)) char key[16], char output_cipher[16]){
  // ...
}

An attribute __attribute__((constant_time)) will indicate that a function needs to be constant-time and shouldn't leak secret key with __attribute__((secret)), then we will do some transformations (for example, do if-conversion to eliminate branches) in the frontend (Clang) and middle end (LLVM IR) to make sure generated code is with this property. There are lots of downstreams/papers doing similar works (for X86, ARM, etc.). Since RISCV has made this constant-time property a standard extension, I think this can be attractive.

But for now, there is still a long way to go. I plan to start from verifying a piece of assemblies as this patch has done.


Go back to your question. :-)
The place where a secret may leak is what we need to protect. If each iteration (without the branch instruction in latch) of a loop is constant-time, then the loop won't leak any information about secret key with or without misprediction (generally speaking).
Actually, Zkt is just a list of instructions that are “safe to use” to handle crypto secrets. So if the branch instructions won't use any registers that hold secrets or effected by secrets, it's OK to be in a "constant-time" loop/function.
I may not explain it clearly, so I lead you to RISC-V Zkt: Portable Timing Attack Resistance (via Dynamic Taint Analysis). :-)

craig.topper added inline comments.Jul 19 2023, 11:03 AM
llvm/lib/Target/RISCV/RISCVInstrInfo.td
688

Can we move this scope start above ADDI? Then we don't need to mention it 3 other times before this.

llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
336

Are ROLW/RORW not in the constant time list? Surely that's a miss in the table in the spec since it says "The Zbkb, Zbkx and Zbkx extensions are included in their entirety."

craig.topper added inline comments.Jul 19 2023, 11:07 AM
llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
336

Should we include c.mul, c.not, and c.zext.b from Zcb? Those map to mul, xor, and andi.

I filed an issue about whether Zba, Zbb, and Zbs should be part of Zkt. https://github.com/riscv/riscv-crypto/issues/348

Should we include c.mul, c.not, and c.zext.b from Zcb? Those map to mul, xor, and andi.

I guess as currently written they aren't constant time. So crypto writers have to disable the Zcb extension I guess.

wangpc updated this revision to Diff 542313.Jul 19 2023, 11:16 PM
wangpc marked 4 inline comments as done.
  • Rebase.
  • Add more Zbkb instructions.
  • Add invalid tests.