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

Constant-time tests for libsecp256k1 #213

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ rand = "0.6"
rand_core = "0.4"
serde_test = "1.0"
bitcoin_hashes = "0.7"
llvm-ir = "^0.5"
pitchfork = { package = "haybale-pitchfork", version = "^0.2" }

[target.wasm32-unknown-unknown.dev-dependencies]
wasm-bindgen-test = "0.3"
Expand Down
16 changes: 16 additions & 0 deletions README_PITCHFORK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
### Build test to emit LLVM bitcode

Haybale-pitchfork requires llvm-sys (LLVM Rust bindings) and boolector to be
installed as shared libraries prior to generating bitcode and compiling this test.

Generate LLVM bitcode:

```
CARGO_INCREMENTAL="" cargo rustc -- -g --emit llvm-bc
```

Run test:

```
cargo test --test pitchfork
```
Empty file added tests/mod.rs
Empty file.
90 changes: 90 additions & 0 deletions tests/pitchfork.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
extern crate llvm_ir;
extern crate pitchfork;

use pitchfork::{
AbstractData,
AbstractValue,
Config,
PitchforkConfig,
Project,
StructDescriptions,
check_for_ct_violation,
};

fn run_pitchfork(fn_name: &String,
args: &Option<Vec<AbstractData>>,
struct_desc: &StructDescriptions) {
// Path to generated bitcode
let mut bc_path = std::env::current_exe().unwrap();
bc_path.pop();

let project = Project::from_bc_dir(&bc_path, "bc").unwrap();

// Get all mangled function names for ConstantTimeEq implementations
let ct_func_names = project
.all_functions()
.filter(|x| x.0.name.contains(fn_name))
.collect::<Vec<(&llvm_ir::Function, &llvm_ir::module::Module)>>();

let mut config = Config::default();
config.loop_bound = 100;

// Test each function for constant-time violations
for func in ct_func_names {
let result = check_for_ct_violation(&func.0.name,
&project,
args.clone(),
&struct_desc,
config.clone(),
&PitchforkConfig::default());

if result.path_results.len() != 0 {
panic!("Constant-time result:\n\n{}", &result);
}
}
}

#[test]
fn test_ct_abs64() {
let args = Some(vec![
AbstractData::pub_pointer_to(AbstractData::sec_integer(64)),
AbstractData::sec_i64(),
]);

let sd = StructDescriptions::new();

run_pitchfork(&String::from("secp256k1_sign_and_abs64"), &args, &sd);
}

#[test]
fn test_ct_sign() {
let args = Some(vec![
AbstractData::pub_pointer_to(AbstractData::default()),
AbstractData::pub_pointer_to(AbstractData::default()),
AbstractData::pub_pointer_to(AbstractData::default()),
AbstractData::pub_pointer_to(AbstractData::secret()),
AbstractData::pub_pointer_to(AbstractData::default()),
AbstractData::pub_pointer_to(AbstractData::default()),
AbstractData::pub_pointer_to(AbstractData::pub_i8(AbstractValue::Unconstrained)),
]);

let sd = StructDescriptions::new();

run_pitchfork(&String::from("secp256k1_ecdsa_sign"), &args, &sd);
}

#[test]
fn test_ct_ecdh() {
let args = Some(vec![
AbstractData::pub_pointer_to(AbstractData::default()),
AbstractData::pub_pointer_to(AbstractData::default()),
AbstractData::pub_pointer_to(AbstractData::default()),
AbstractData::pub_pointer_to(AbstractData::secret()),
AbstractData::default(),
AbstractData::pub_pointer_to(AbstractData::default()),
]);

let sd = StructDescriptions::new();

run_pitchfork(&String::from("secp256k1_ecdh"), &args, &sd);
}