Valgrind ctime is a simple, but very powerful constant time checker for crypto code. While it works well for C code, there's no good bidings of valgrind's libs AFAIK, and it'll likely be a complex task to accomplish anyway.
Here's how this works:
1 - Write your crypto code
2 - Write some tests (in Rust), doing crypto stuff. This should be implemented as a ffi-safe method, like this
#[no_mangle]
pub extern "C" fn do_some_stuff(
key: *const u8,
input: *const u8,
input_len: usize,
) {
// your code here
}
We are interested in the secret data, in this case, the key. Not being constant time with the input or public keys is not a problem.
3 - Now you need to append the following to your Cargo.toml
[lib]
crate-type = ["staticlib"]
This will make a static lib that we can link to our C code.
4 - Now you need to write a C file that will call your Rust code.
#include <stdint.h>
#include <stdio.h>
extern void do_some_stuff(uint8_t *key, uint8_t *input, size_t input_len);
int main() {
uint8_t key[32] = {0};
uint8_t input[32] = {0};
// Here's the important part. Although we initialized the key, we tell valgrind to treat it as uninitialized. If we have a operation that depends on the key, valgrind will complain, and we'll catch this.
VALGRIND_MAKE_MEM_UNDEFINED(&key, 4);
do_some_stuff(key, input, 32);
return 0;
}
5 - Compile your C code with valgrind's headers and libs. You can use the following command:
gcc -g -O0 -L $RUST_LIB/target/debug/ -l:librust_bip324.so -o glue glue.c
LD_LIBRARY_PATH=$RUST_LIB/target/debug/ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --track-origins=yes ./glue
If any of your crypto code is not constant time, valgrind will complain, and you'll see something like this:
==1234== Conditional jump or move depends on uninitialised value(s)
Note that valgrind may give false positives, so you should check if the code is really not constant time. If it is, you can use the following to silence valgrind:
VALGRIND_MAKE_MEM_DEFINED(&key, 4);