Skip to content

Commit 68755f3

Browse files
committed
fuzz: implement ECDH
It is now possible for the fuzzer to generate (a) an ECDH pair that'll pass some form of verification (at least assuming the user passes a crappy hash); (b) a signature that will pass verification. The one remaining crypto-hard thing in this lib is the keypair tweak_add and tweak_add_check API; there isn't a good way to simulate this in the fuzzer without completely rewriting the public key parsing/serialization framework, which is a lot of work and would also reduce the fuzztest coverage of the C library.
1 parent f978dcc commit 68755f3

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed

secp256k1-sys/src/lib.rs

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -414,16 +414,6 @@ extern "C" {
414414
n: c_int)
415415
-> c_int;
416416

417-
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdh")]
418-
pub fn secp256k1_ecdh(
419-
cx: *const Context,
420-
output: *mut c_uchar,
421-
pubkey: *const PublicKey,
422-
seckey: *const c_uchar,
423-
hashfp: EcdhHashFn,
424-
data: *mut c_void,
425-
) -> c_int;
426-
427417
// Extra keys
428418
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_keypair_create")]
429419
pub fn secp256k1_keypair_create(
@@ -489,6 +479,17 @@ extern "C" {
489479

490480
#[cfg(not(rust_secp_fuzz))]
491481
extern "C" {
482+
// ECDH
483+
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdh")]
484+
pub fn secp256k1_ecdh(
485+
cx: *const Context,
486+
output: *mut c_uchar,
487+
pubkey: *const PublicKey,
488+
seckey: *const c_uchar,
489+
hashfp: EcdhHashFn,
490+
data: *mut c_void,
491+
) -> c_int;
492+
492493
// ECDSA
493494
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_verify")]
494495
pub fn secp256k1_ecdsa_verify(cx: *const Context,
@@ -678,6 +679,38 @@ impl<T> CPtr for [T] {
678679
mod fuzz_dummy {
679680
use super::*;
680681

682+
// ECDH
683+
/// Sets out to point[0..32] ^ seckey[0..32] ^ data
684+
pub unsafe fn secp256k1_ecdh(
685+
cx: *const Context,
686+
output: *mut c_uchar,
687+
pubkey: *const PublicKey,
688+
seckey: *const c_uchar,
689+
hashfp: EcdhHashFn,
690+
data: *mut c_void,
691+
) -> c_int {
692+
// No context requirements
693+
assert!(!cx.is_null());
694+
695+
if let Some(hashfp) = hashfp {
696+
hashfp(output, (*pubkey).0[0..32].as_ptr(), seckey, data)
697+
} else {
698+
let output_sl = slice::from_raw_parts_mut(output as *mut u8, 32);
699+
let sk_sl = slice::from_raw_parts(seckey as *const u8, 32);
700+
output_sl.copy_from_slice(&(*pubkey).0[0..32]);
701+
for i in 0..32 {
702+
output_sl[i] ^= sk_sl[i];
703+
}
704+
if !data.is_null() {
705+
let data_sl = slice::from_raw_parts(data as *const u8, 32);
706+
for i in 0..32 {
707+
output_sl[i] ^= data_sl[i];
708+
}
709+
}
710+
1
711+
}
712+
}
713+
681714
// ECDSA
682715
/// Verifies that sig is msg32||pk[..32]
683716
pub unsafe fn secp256k1_ecdsa_verify(cx: *const Context,
@@ -745,8 +778,8 @@ mod fuzz_dummy {
745778
sig64: *mut c_uchar,
746779
msg32: *const c_uchar,
747780
keypair: *const KeyPair,
748-
noncefp: SchnorrNonceFn,
749-
noncedata: *const c_void
781+
_noncefp: SchnorrNonceFn,
782+
_noncedata: *const c_void
750783
) -> c_int {
751784
// Check context is built for signing
752785
let mut new_kp = KeyPair::new();

0 commit comments

Comments
 (0)