Skip to content

Instantly share code, notes, and snippets.

@Davidson-Souza
Created July 13, 2023 16:44
Show Gist options
  • Save Davidson-Souza/e90fb262ed73ad6c6d8f7d74f0d87ec9 to your computer and use it in GitHub Desktop.
Save Davidson-Souza/e90fb262ed73ad6c6d8f7d74f0d87ec9 to your computer and use it in GitHub Desktop.
Using valgrind ctime with Rust code, without biding valgrind lib
/// Tests encryption and decryption of chacha, using the ctime tick. I'm using https://github.com/Adidev-KGP/rust-bip324, rev f252af3a9925877a1f6d50bfee27eec388d62094
#[no_mangle]
pub extern "C" fn chacha_rtt(
key: *const u8,
input: *const u8,
input_len: usize,
_output: *mut *mut u8,
) {
let input_key = unsafe { std::slice::from_raw_parts(key, 32) };
let mut key = [0u8; 32];
key.copy_from_slice(input_key);
let input = unsafe { std::slice::from_raw_parts(input, input_len) };
let mut chacha = FsChaCha20::FSChaCha20::new(key, 300);
let enc = chacha.encrypt(input);
let _ = chacha.decrypt(&enc);
}
// If you apply the diff bellow, you'll see a warning about key not being initialized.
diff --git a/src/FsChaCha20/fschacha20.rs b/src/FsChaCha20/fschacha20.rs
index ba8e185..781c3e1 100644
--- a/src/FsChaCha20/fschacha20.rs
+++ b/src/FsChaCha20/fschacha20.rs
@@ -54,6 +54,9 @@ impl FSChaCha20 {
}
pub fn decrypt(&mut self, chunk: &[u8]) -> Vec<u8> {
+ if self.key[0] == 0 {
+ println!("Key is not initialized");
+ }
self.crypt(chunk)
}
}

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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment