From 40c31342f2e1fcce5a49a8a2de7f88a5bd11e439 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Tue, 22 Dec 2020 21:17:31 +0000 Subject: [PATCH 1/5] ffi: make function types nullable --- secp256k1-sys/src/lib.rs | 23 ++++++++++++----------- src/ecdh.rs | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/secp256k1-sys/src/lib.rs b/secp256k1-sys/src/lib.rs index 3828435..d0f95fa 100644 --- a/secp256k1-sys/src/lib.rs +++ b/secp256k1-sys/src/lib.rs @@ -58,36 +58,37 @@ pub const SECP256K1_SER_COMPRESSED: c_uint = (1 << 1) | (1 << 8); /// around the FFI functions to use it. And it's an unsafe type. /// Nonces are generated deterministically by RFC6979 by /// default; there should be no need to ever change this. -pub type NonceFn = unsafe extern "C" fn(nonce32: *mut c_uchar, - msg32: *const c_uchar, - key32: *const c_uchar, - algo16: *const c_uchar, - data: *mut c_void, - attempt: c_uint, -) -> c_int; +pub type NonceFn = Option c_int>; /// Hash function to use to post-process an ECDH point to get /// a shared secret. -pub type EcdhHashFn = unsafe extern "C" fn( +pub type EcdhHashFn = Option c_int; +) -> c_int>; /// Same as secp256k1_nonce function with the exception of accepting an /// additional pubkey argument and not requiring an attempt argument. The pubkey /// argument can protect signature schemes with key-prefixed challenge hash /// inputs against reusing the nonce when signing with the wrong precomputed /// pubkey. -pub type SchnorrNonceFn = unsafe extern "C" fn( +pub type SchnorrNonceFn = Option c_int; +) -> c_int>; /// A Secp256k1 context, containing various precomputed values and such /// needed to do elliptic curve computations. If you create one of these diff --git a/src/ecdh.rs b/src/ecdh.rs index e76b54f..51ec005 100644 --- a/src/ecdh.rs +++ b/src/ecdh.rs @@ -151,7 +151,7 @@ impl SharedSecret { xy.as_mut_ptr(), point.as_ptr(), scalar.as_ptr(), - c_callback, + Some(c_callback), ptr::null_mut(), ) }; From b811ec133a0628f9db0e452abf84b8e302737f58 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Tue, 22 Dec 2020 20:16:10 +0000 Subject: [PATCH 2/5] fuzz: only replace signing and verification, leave everything else alone We can now run unit tests with the fuzz feature on, and they'll pass, which is some assurance that fuzzing with the feature on won't lead to spurious failures due to the fuzz harness inadequately simulating message signing. --- secp256k1-sys/src/lib.rs | 631 +++++++-------------------------------- src/lib.rs | 1 + src/schnorrsig.rs | 2 + 3 files changed, 119 insertions(+), 515 deletions(-) diff --git a/secp256k1-sys/src/lib.rs b/secp256k1-sys/src/lib.rs index d0f95fa..7a8d666 100644 --- a/secp256k1-sys/src/lib.rs +++ b/secp256k1-sys/src/lib.rs @@ -264,7 +264,6 @@ impl hash::Hash for KeyPair { } } -#[cfg(not(rust_secp_fuzz))] extern "C" { /// Default ECDH hash function #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdh_hash_function_default")] @@ -276,6 +275,9 @@ extern "C" { #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_default")] pub static secp256k1_nonce_function_default: NonceFn; + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_bip340")] + pub static secp256k1_nonce_function_bip340: SchnorrNonceFn; + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_context_no_precomp")] pub static secp256k1_context_no_precomp: *const Context; @@ -343,35 +345,10 @@ extern "C" { in_sig: *const Signature) -> c_int; - // ECDSA - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_verify")] - pub fn secp256k1_ecdsa_verify(cx: *const Context, - sig: *const Signature, - msg32: *const c_uchar, - pk: *const PublicKey) - -> c_int; - - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_sign")] - pub fn secp256k1_ecdsa_sign(cx: *const Context, - sig: *mut Signature, - msg32: *const c_uchar, - sk: *const c_uchar, - noncefn: NonceFn, - noncedata: *const c_void) - -> c_int; - - // EC #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_seckey_verify")] pub fn secp256k1_ec_seckey_verify(cx: *const Context, sk: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_create")] - pub fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey, - sk: *const c_uchar) -> c_int; - -//TODO secp256k1_ec_privkey_export -//TODO secp256k1_ec_privkey_import - #[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_add function instead")] #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_negate")] pub fn secp256k1_ec_privkey_negate(cx: *const Context, @@ -381,10 +358,6 @@ extern "C" { pub fn secp256k1_ec_seckey_negate(cx: *const Context, sk: *mut c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_negate")] - pub fn secp256k1_ec_pubkey_negate(cx: *const Context, - pk: *mut PublicKey) -> c_int; - #[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_add function instead")] #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_tweak_add")] pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context, @@ -398,12 +371,6 @@ extern "C" { tweak: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_tweak_add")] - pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, - pk: *mut PublicKey, - tweak: *const c_uchar) - -> c_int; - #[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_mul function instead")] #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_tweak_mul")] pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context, @@ -417,6 +384,23 @@ extern "C" { tweak: *const c_uchar) -> c_int; + // EC + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_create")] + pub fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey, + sk: *const c_uchar) -> c_int; + + + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_negate")] + pub fn secp256k1_ec_pubkey_negate(cx: *const Context, + pk: *mut PublicKey) -> c_int; + + + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_tweak_add")] + pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, + pk: *mut PublicKey, + tweak: *const c_uchar) + -> c_int; + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_tweak_mul")] pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, pk: *mut PublicKey, @@ -440,31 +424,7 @@ extern "C" { data: *mut c_void, ) -> c_int; - - // Schnorr Signatures - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_bip340")] - pub static secp256k1_nonce_function_bip340: SchnorrNonceFn; - - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_schnorrsig_sign")] - pub fn secp256k1_schnorrsig_sign( - cx: *const Context, - sig: *mut c_uchar, - msg32: *const c_uchar, - keypair: *const KeyPair, - noncefp: SchnorrNonceFn, - noncedata: *const c_void - ) -> c_int; - - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_schnorrsig_verify")] - pub fn secp256k1_schnorrsig_verify( - cx: *const Context, - sig64: *const c_uchar, - msg32: *const c_uchar, - pubkey: *const XOnlyPublicKey, - ) -> c_int; - // Extra keys - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_keypair_create")] pub fn secp256k1_keypair_create( cx: *const Context, @@ -527,6 +487,45 @@ extern "C" { ) -> c_int; } +#[cfg(not(rust_secp_fuzz))] +extern "C" { + // ECDSA + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_verify")] + pub fn secp256k1_ecdsa_verify(cx: *const Context, + sig: *const Signature, + msg32: *const c_uchar, + pk: *const PublicKey) + -> c_int; + + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_sign")] + pub fn secp256k1_ecdsa_sign(cx: *const Context, + sig: *mut Signature, + msg32: *const c_uchar, + sk: *const c_uchar, + noncefn: NonceFn, + noncedata: *const c_void) + -> c_int; + + // Schnorr Signatures + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_schnorrsig_sign")] + pub fn secp256k1_schnorrsig_sign( + cx: *const Context, + sig: *mut c_uchar, + msg32: *const c_uchar, + keypair: *const KeyPair, + noncefp: SchnorrNonceFn, + noncedata: *const c_void + ) -> c_int; + + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_schnorrsig_verify")] + pub fn secp256k1_schnorrsig_verify( + cx: *const Context, + sig64: *const c_uchar, + msg32: *const c_uchar, + pubkey: *const XOnlyPublicKey, + ) -> c_int; +} + /// A reimplementation of the C function `secp256k1_context_create` in rust. /// @@ -675,221 +674,31 @@ impl CPtr for [T] { } } - - - #[cfg(rust_secp_fuzz)] mod fuzz_dummy { - extern crate std; - use self::std::{ptr, mem}; - use self::std::boxed::Box; - use types::*; - use {Signature, Context, NonceFn, EcdhHashFn, PublicKey, - SchnorrNonceFn, XOnlyPublicKey, KeyPair, - SECP256K1_START_NONE, SECP256K1_START_VERIFY, SECP256K1_START_SIGN, - SECP256K1_SER_COMPRESSED, SECP256K1_SER_UNCOMPRESSED}; - - #[allow(non_upper_case_globals)] - pub static secp256k1_context_no_precomp: &Context = &Context(0); - - extern "C" { - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdh_hash_function_default")] - pub static secp256k1_ecdh_hash_function_default: EcdhHashFn; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_rfc6979")] - pub static secp256k1_nonce_function_rfc6979: NonceFn; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_bip340")] - pub static secp256k1_nonce_function_bip340: SchnorrNonceFn; - } - - // Contexts - /// Creates a dummy context, tracking flags to ensure proper calling semantics - pub unsafe fn secp256k1_context_preallocated_create(_ptr: *mut c_void, flags: c_uint) -> *mut Context { - let b = Box::new(Context(flags as i32)); - Box::into_raw(b) - } - - /// Return dummy size of context struct. - pub unsafe fn secp256k1_context_preallocated_size(_flags: c_uint) -> size_t { - mem::size_of::() - } - - /// Return dummy size of context struct. - pub unsafe fn secp256k1_context_preallocated_clone_size(_cx: *mut Context) -> size_t { - mem::size_of::() - } - - /// Copies a dummy context - pub unsafe fn secp256k1_context_preallocated_clone(cx: *const Context, prealloc: *mut c_void) -> *mut Context { - let ret = prealloc as *mut Context; - *ret = (*cx).clone(); - ret - } - - /// "Destroys" a dummy context - pub unsafe fn secp256k1_context_preallocated_destroy(cx: *mut Context) { - (*cx).0 = 0; - } - - /// Asserts that cx is properly initialized - pub unsafe fn secp256k1_context_randomize(cx: *mut Context, - _seed32: *const c_uchar) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - 1 - } - - // Pubkeys - /// Parse 33/65 byte pubkey into PublicKey, losing compressed information - pub unsafe fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey, - input: *const c_uchar, in_len: size_t) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - match in_len { - 33 => { - if (*input.offset(1) > 0x7f && *input != 2) || (*input.offset(1) <= 0x7f && *input != 3) { - 0 - } else { - ptr::copy(input.offset(1), (*pk).0[0..32].as_mut_ptr(), 32); - ptr::copy(input.offset(1), (*pk).0[32..64].as_mut_ptr(), 32); - test_pk_validate(cx, pk) - } - }, - 65 => { - if *input != 4 && *input != 6 && *input != 7 { - 0 - } else { - ptr::copy(input.offset(1), (*pk).0.as_mut_ptr(), 64); - test_pk_validate(cx, pk) - } - }, - _ => 0 - } - } - - /// Serialize PublicKey back to 33/65 byte pubkey - pub unsafe fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar, - out_len: *mut size_t, pk: *const PublicKey, - compressed: c_uint) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if test_pk_validate(cx, pk) != 1 { return 0; } - if compressed == SECP256K1_SER_COMPRESSED { - assert_eq!(*out_len, 33); - if (*pk).0[0] > 0x7f { - *output = 2; - } else { - *output = 3; - } - ptr::copy((*pk).0.as_ptr(), output.offset(1), 32); - } else if compressed == SECP256K1_SER_UNCOMPRESSED { - assert_eq!(*out_len, 65); - *output = 4; - ptr::copy((*pk).0.as_ptr(), output.offset(1), 64); - } else { - panic!("Bad flags"); - } - 1 - } - - // Signatures - pub unsafe fn secp256k1_ecdsa_signature_parse_der(_cx: *const Context, _sig: *mut Signature, - _input: *const c_uchar, _in_len: size_t) - -> c_int { - unimplemented!(); - } - - /// Copies input64 to sig, checking the pubkey part is valid - pub unsafe fn secp256k1_ecdsa_signature_parse_compact(cx: *const Context, sig: *mut Signature, - input64: *const c_uchar) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if secp256k1_ec_seckey_verify(cx, input64.offset(32)) != 1 { return 0; } // sig should be msg32||sk - ptr::copy(input64, (*sig).0[..].as_mut_ptr(), 64); - 1 - } - - pub unsafe fn ecdsa_signature_parse_der_lax(_cx: *const Context, _sig: *mut Signature, - _input: *const c_uchar, _in_len: size_t) - -> c_int { - unimplemented!(); - } - - /// Copies up to 72 bytes into output from sig - pub unsafe fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *mut c_uchar, - out_len: *mut size_t, sig: *const Signature) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - - let mut len_r = 33; - if *(*sig).0.as_ptr().offset(0) < 0x80 { - len_r -= 1; - } - let mut len_s = 33; - if *(*sig).0.as_ptr().offset(32) < 0x80 { - len_s -= 1; - } - - assert!(*out_len >= (6 + len_s + len_r) as usize); - - *output.offset(0) = 0x30; - *output.offset(1) = 4 + len_r + len_s; - *output.offset(2) = 0x02; - *output.offset(3) = len_r; - if len_r == 33 { - *output.offset(4) = 0; - ptr::copy((*sig).0[..].as_ptr(), output.offset(5), 32); - } else { - ptr::copy((*sig).0[..].as_ptr(), output.offset(4), 32); - } - *output.offset(4 + len_r as isize) = 0x02; - *output.offset(5 + len_r as isize) = len_s; - if len_s == 33 { - *output.offset(6 + len_r as isize) = 0; - ptr::copy((*sig).0[..].as_ptr().offset(32), output.offset(7 + len_r as isize), 32); - } else { - ptr::copy((*sig).0[..].as_ptr().offset(32), output.offset(6 + len_r as isize), 32); - } - 1 - } - - /// Copies sig to output64 - pub unsafe fn secp256k1_ecdsa_signature_serialize_compact(cx: *const Context, output64: *mut c_uchar, - sig: *const Signature) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - ptr::copy((*sig).0[..].as_ptr(), output64, 64); - 1 - } - - pub unsafe fn secp256k1_ecdsa_signature_normalize(_cx: *const Context, _out_sig: *mut Signature, - _in_sig: *const Signature) - -> c_int { - unimplemented!(); - } + use super::*; // ECDSA - /// Verifies that sig is msg32||pk[0..32] + /// Verifies that sig is msg32||pk[..32] pub unsafe fn secp256k1_ecdsa_verify(cx: *const Context, sig: *const Signature, msg32: *const c_uchar, pk: *const PublicKey) -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - assert!((*cx).0 as u32 & SECP256K1_START_VERIFY == SECP256K1_START_VERIFY); - if test_pk_validate(cx, pk) != 1 { return 0; } - for i in 0..32 { - if (*sig).0[i] != *msg32.offset(i as isize) { - return 0; - } - } - if (*sig).0[32..64] != (*pk).0[0..32] { - 0 - } else { + // Check context is built for verification + let mut new_pk = (*pk).clone(); + let _ = secp256k1_ec_pubkey_tweak_add(cx, &mut new_pk, msg32); + // Actually verify + let sig_sl = slice::from_raw_parts(sig as *const u8, 64); + let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); + if &sig_sl[..32] == msg_sl && sig_sl[32..] == (*pk).0[0..32] { 1 + } else { + 0 } } - /// Sets sig to msg32||sk + /// Sets sig to msg32||pk[..32] pub unsafe fn secp256k1_ecdsa_sign(cx: *const Context, sig: *mut Signature, msg32: *const c_uchar, @@ -897,274 +706,66 @@ mod fuzz_dummy { _noncefn: NonceFn, _noncedata: *const c_void) -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - assert!((*cx).0 as u32 & SECP256K1_START_SIGN == SECP256K1_START_SIGN); - if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } - ptr::copy(msg32, (*sig).0[0..32].as_mut_ptr(), 32); - ptr::copy(sk, (*sig).0[32..64].as_mut_ptr(), 32); - 1 - } - - // EC - /// Checks that pk != 0xffff...ffff and pk[0..32] == pk[32..64] - pub unsafe fn test_pk_validate(cx: *const Context, - pk: *const PublicKey) -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if (*pk).0[0..32] != (*pk).0[32..64] || secp256k1_ec_seckey_verify(cx, (*pk).0[0..32].as_ptr()) == 0 { - 0 - } else { - 1 + // Check context is built for signing (and compute pk) + let mut new_pk = PublicKey::new(); + if secp256k1_ec_pubkey_create(cx, &mut new_pk, sk) != 1 { + return 0; } - } - - /// Checks that sk != 0xffff...ffff - pub unsafe fn secp256k1_ec_seckey_verify(cx: *const Context, - sk: *const c_uchar) -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - let mut res = 0; - for i in 0..32 { - if *sk.offset(i as isize) != 0xff { res = 1 }; - } - res - } - - /// Sets pk to sk||sk - pub unsafe fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey, - sk: *const c_uchar) -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } - ptr::copy(sk, (*pk).0[0..32].as_mut_ptr(), 32); - ptr::copy(sk, (*pk).0[32..64].as_mut_ptr(), 32); + // Sign + let sig_sl = slice::from_raw_parts_mut(sig as *mut u8, 64); + let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); + sig_sl[..32].copy_from_slice(msg_sl); + sig_sl[32..].copy_from_slice(&new_pk.0[..32]); 1 } -//TODO secp256k1_ec_privkey_export -//TODO secp256k1_ec_privkey_import - - #[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_negate function instead")] - pub unsafe fn secp256k1_ec_privkey_negate(cx: *const Context, - sk: *mut c_uchar) -> c_int { - secp256k1_ec_seckey_negate(cx, sk) - } - - pub unsafe fn secp256k1_ec_seckey_negate(cx: *const Context, - sk: *mut c_uchar) -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } - 1 - } - - pub unsafe fn secp256k1_ec_pubkey_negate(cx: *const Context, - pk: *mut PublicKey) -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if test_pk_validate(cx, pk) != 1 { return 0; } - 1 - } - - /// Copies the first 16 bytes of tweak into the last 16 bytes of sk - pub unsafe fn secp256k1_ec_privkey_tweak_add(cx: *const Context, - sk: *mut c_uchar, - tweak: *const c_uchar) - -> c_int { - secp256k1_ec_seckey_tweak_add(cx, sk, tweak) - } - - pub unsafe fn secp256k1_ec_seckey_tweak_add(cx: *const Context, - sk: *mut c_uchar, - tweak: *const c_uchar) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } - ptr::copy(tweak.offset(16), sk.offset(16), 16); - *sk.offset(24) = 0x7f; // Ensure sk remains valid no matter what tweak was - 1 - } - - /// The PublicKey equivalent of secp256k1_ec_privkey_tweak_add - pub unsafe fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, - pk: *mut PublicKey, - tweak: *const c_uchar) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if test_pk_validate(cx, pk) != 1 { return 0; } - ptr::copy(tweak.offset(16), (*pk).0[16..32].as_mut_ptr(), 16); - ptr::copy(tweak.offset(16), (*pk).0[16+32..64].as_mut_ptr(), 16); - (*pk).0[24] = 0x7f; // Ensure pk remains valid no matter what tweak was - (*pk).0[24+32] = 0x7f; // Ensure pk remains valid no matter what tweak was - 1 - } - - /// Copies the last 16 bytes of tweak into the last 16 bytes of sk - pub unsafe fn secp256k1_ec_privkey_tweak_mul(cx: *const Context, - sk: *mut c_uchar, - tweak: *const c_uchar) - -> c_int { - secp256k1_ec_seckey_tweak_mul(cx, sk, tweak) - } - - /// Copies the last 16 bytes of tweak into the last 16 bytes of sk - pub unsafe fn secp256k1_ec_seckey_tweak_mul(cx: *const Context, - sk: *mut c_uchar, - tweak: *const c_uchar) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } - ptr::copy(tweak.offset(16), sk.offset(16), 16); - *sk.offset(24) = 0x00; // Ensure sk remains valid no matter what tweak was - 1 - } - - /// The PublicKey equivalent of secp256k1_ec_privkey_tweak_mul - pub unsafe fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, - pk: *mut PublicKey, - tweak: *const c_uchar) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if test_pk_validate(cx, pk) != 1 { return 0; } - ptr::copy(tweak.offset(16), (*pk).0[16..32].as_mut_ptr(), 16); - ptr::copy(tweak.offset(16), (*pk).0[16+32..64].as_mut_ptr(), 16); - (*pk).0[24] = 0x00; // Ensure pk remains valid no matter what tweak was - (*pk).0[24+32] = 0x00; // Ensure pk remains valid no matter what tweak was - 1 - } - - pub unsafe fn secp256k1_ec_pubkey_combine(cx: *const Context, - out: *mut PublicKey, - ins: *const *const PublicKey, - n: c_int) - -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - assert!(n <= 32 && n >= 0); //TODO: Remove this restriction? - for i in 0..n { - if test_pk_validate(cx, *ins.offset(i as isize)) != 1 { return 0; } - (*out).0[(i*32/n) as usize..((i+1)*32/n) as usize].copy_from_slice(&(**ins.offset(i as isize)).0[(i*32/n) as usize..((i+1)*32/n) as usize]); - } - ptr::copy((*out).0[0..32].as_ptr(), (*out).0[32..64].as_mut_ptr(), 32); - (*out).0[24] = 0x7f; // pk should always be valid - (*out).0[24+32] = 0x7f; // pk should always be valid - test_pk_validate(cx, out) - } - - /// Sets out to point[0..16]||scalar[0..16] - pub unsafe fn secp256k1_ecdh( - cx: *const Context, - out: *mut c_uchar, - point: *const PublicKey, - scalar: *const c_uchar, - _hashfp: EcdhHashFn, - _data: *mut c_void, - ) -> c_int { - assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - if secp256k1_ec_seckey_verify(cx, scalar) != 1 { return 0; } - - let mut scalar_prefix = [0; 16]; - ptr::copy(scalar, scalar_prefix[..].as_mut_ptr(), 16); - - if (*point).0[0..16] > scalar_prefix[0..16] { - ptr::copy((*point).as_ptr(), out, 16); - ptr::copy(scalar, out.offset(16), 16); - } else { - ptr::copy(scalar, out, 16); - ptr::copy((*point).as_ptr(), out.offset(16), 16); - } - (*out.offset(16)) = 0x00; // result should always be a valid secret key - 1 - } - - pub unsafe fn secp256k1_schnorrsig_sign( - _cx: *const Context, - _sig: *mut c_uchar, - _msg32: *const c_uchar, - _keypair: *const KeyPair, - _noncefp: SchnorrNonceFn, - _noncedata: *const c_void - ) -> c_int { - unimplemented!(); - } - + /// Verifies that sig is msg32||pk[32..] pub unsafe fn secp256k1_schnorrsig_verify( - _cx: *const Context, - _sig64: *const c_uchar, - _msg32: *const c_uchar, - _pubkey: *const XOnlyPublicKey, + cx: *const Context, + sig64: *const c_uchar, + msg32: *const c_uchar, + pubkey: *const XOnlyPublicKey, ) -> c_int { - unimplemented!(); + // Check context is built for verification + let mut new_pk = PublicKey::new(); + let _ = secp256k1_xonly_pubkey_tweak_add(cx, &mut new_pk, pubkey, msg32); + // Actually verify + let sig_sl = slice::from_raw_parts(sig64 as *const u8, 64); + let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); + if &sig_sl[..32] == msg_sl && sig_sl[32..] == (*pubkey).0[..32] { + 1 + } else { + 0 + } } - pub fn secp256k1_xonly_pubkey_parse( - _cx: *const Context, - _pubkey: *mut XOnlyPublicKey, - _input32: *const c_uchar, + /// Sets sig to msg32||pk[..32] + pub unsafe fn secp256k1_schnorrsig_sign( + cx: *const Context, + sig64: *mut c_uchar, + msg32: *const c_uchar, + keypair: *const KeyPair, + noncefp: SchnorrNonceFn, + noncedata: *const c_void ) -> c_int { - unimplemented!(); - } - - pub fn secp256k1_xonly_pubkey_serialize( - _cx: *const Context, - _output32: *mut c_uchar, - _pubkey: *const XOnlyPublicKey, - ) -> c_int { - unimplemented!(); - } - - pub unsafe fn secp256k1_xonly_pubkey_from_pubkey( - _cx: *const Context, - _xonly_pubkey: *mut XOnlyPublicKey, - _pk_parity: *mut c_int, - _pubkey: *const PublicKey, - ) -> c_int { - unimplemented!(); - } - - pub unsafe fn secp256k1_keypair_create( - _cx: *const Context, - _keypair: *mut KeyPair, - _seckey: *const c_uchar, - ) -> c_int { - unimplemented!(); - } - - pub unsafe fn secp256k1_xonly_pubkey_tweak_add( - _cx: *const Context, - _output_pubkey: *mut PublicKey, - _internal_pubkey: *const XOnlyPublicKey, - _tweak32: *const c_uchar, - ) -> c_int { - unimplemented!(); - } - - pub unsafe fn secp256k1_keypair_xonly_pub( - _cx: *const Context, - _pubkey: *mut XOnlyPublicKey, - _pk_parity: *mut c_int, - _keypair: *const KeyPair - ) -> c_int { - unimplemented!(); - } - - pub unsafe fn secp256k1_keypair_xonly_tweak_add( - _cx: *const Context, - _keypair: *mut KeyPair, - _tweak32: *const c_uchar, - ) -> c_int { - unimplemented!(); - } - - pub unsafe fn secp256k1_xonly_pubkey_tweak_add_check( - _cx: *const Context, - _tweaked_pubkey32: *const c_uchar, - _tweaked_pubkey_parity: c_int, - _internal_pubkey: *const XOnlyPublicKey, - _tweak32: *const c_uchar, - ) -> c_int { - unimplemented!(); + // Check context is built for signing + let mut new_kp = KeyPair::new(); + if secp256k1_keypair_create(cx, &mut new_kp, (*keypair).0.as_ptr()) != 1 { + return 0; + } + assert_eq!(new_kp, *keypair); + // Sign + let sig_sl = slice::from_raw_parts_mut(sig64 as *mut u8, 64); + let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); + sig_sl[..32].copy_from_slice(msg_sl); + sig_sl[32..].copy_from_slice(&new_kp.0[32..64]); + 1 } } #[cfg(rust_secp_fuzz)] pub use self::fuzz_dummy::*; - #[cfg(test)] mod tests { #[no_mangle] diff --git a/src/lib.rs b/src/lib.rs index 9016d0b..b4eddd7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1172,6 +1172,7 @@ mod tests { } #[test] + #[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs fn test_low_s() { // nb this is a transaction on testnet // txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9 diff --git a/src/schnorrsig.rs b/src/schnorrsig.rs index c55fca1..f637456 100644 --- a/src/schnorrsig.rs +++ b/src/schnorrsig.rs @@ -561,6 +561,7 @@ mod tests { } #[test] + #[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs fn test_schnorrsig_sign() { let secp = Secp256k1::new(); @@ -582,6 +583,7 @@ mod tests { } #[test] + #[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs fn test_schnorrsig_verify() { let secp = Secp256k1::new(); From 96862b6a74e40aff14edfb07a35d873a09b86906 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 23 Dec 2020 18:00:34 +0000 Subject: [PATCH 3/5] fuzz: implement recoverable signatures, get all tests passing, run them in CI --- contrib/test.sh | 11 +++- secp256k1-sys/src/lib.rs | 7 -- secp256k1-sys/src/recovery.rs | 119 ++++++++++++++++++++-------------- src/lib.rs | 2 + src/recovery.rs | 1 + src/schnorrsig.rs | 1 + 6 files changed, 82 insertions(+), 59 deletions(-) diff --git a/contrib/test.sh b/contrib/test.sh index 7befc21..5f9203d 100755 --- a/contrib/test.sh +++ b/contrib/test.sh @@ -33,12 +33,17 @@ if [ "$DO_FEATURE_MATRIX" = true ]; then cargo test --all --features="$feature" done - # Other combos - RUSTFLAGS='--cfg=rust_secp_fuzz' cargo test --no-run --all - RUSTFLAGS='--cfg=rust_secp_fuzz' cargo test --no-run --all --features="recovery" + # Other combos + RUSTFLAGS='--cfg=rust_secp_fuzz' cargo test --all + RUSTFLAGS='--cfg=rust_secp_fuzz' cargo test --all --features="$FEATURES" cargo test --all --features="rand rand-std" cargo test --all --features="rand serde" + if [ "$DO_BENCH" = true ]; then # proxy for us having a nightly compiler + cargo test --all --all-features + RUSTFLAGS='--cfg=rust_secp_fuzz' RUSTDOCFLAGS='--cfg=rust_secp_fuzz' cargo test --all --all-features + fi + # Examples cargo run --example sign_verify cargo run --example sign_verify_recovery --features=recovery diff --git a/secp256k1-sys/src/lib.rs b/secp256k1-sys/src/lib.rs index 7a8d666..72fe4ec 100644 --- a/secp256k1-sys/src/lib.rs +++ b/secp256k1-sys/src/lib.rs @@ -97,13 +97,6 @@ pub type SchnorrNonceFn = Option u32 { - self.0 as u32 - } -} - /// Library-internal representation of a Secp256k1 public key #[repr(C)] pub struct PublicKey([c_uchar; 64]); diff --git a/secp256k1-sys/src/recovery.rs b/secp256k1-sys/src/recovery.rs index 9b9464b..683eef4 100644 --- a/secp256k1-sys/src/recovery.rs +++ b/secp256k1-sys/src/recovery.rs @@ -16,8 +16,7 @@ //! # FFI of the recovery module use ::types::*; -#[cfg(not(rust_secp_fuzz))] -use ::{Context, Signature, NonceFn, PublicKey}; +use {Context, Signature, NonceFn, PublicKey}; /// Library-internal representation of a Secp256k1 signature + recovery ID #[repr(C)] @@ -36,7 +35,6 @@ impl Default for RecoverableSignature { } } -#[cfg(not(rust_secp_fuzz))] extern "C" { #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_recoverable_signature_parse_compact")] pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature, @@ -52,6 +50,10 @@ extern "C" { pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, sig: *mut Signature, input: *const RecoverableSignature) -> c_int; +} + +#[cfg(not(rust_secp_fuzz))] +extern "C" { #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_sign_recoverable")] pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, sig: *mut RecoverableSignature, @@ -72,58 +74,77 @@ extern "C" { #[cfg(rust_secp_fuzz)] mod fuzz_dummy { - extern crate std; - use self::std::ptr; - use super::RecoverableSignature; - use types::*; - use ::{Signature, Context, PublicKey, NonceFn, secp256k1_ec_seckey_verify, - SECP256K1_START_NONE, SECP256K1_START_VERIFY, SECP256K1_START_SIGN}; + use super::*; + use std::slice; - pub unsafe fn secp256k1_ecdsa_recoverable_signature_parse_compact(_cx: *const Context, _sig: *mut RecoverableSignature, - _input64: *const c_uchar, _recid: c_int) - -> c_int { - unimplemented!(); - } + use secp256k1_ec_pubkey_create; + use secp256k1_ec_pubkey_parse; + use secp256k1_ec_pubkey_serialize; + use SECP256K1_SER_COMPRESSED; - pub unsafe fn secp256k1_ecdsa_recoverable_signature_serialize_compact(_cx: *const Context, _output64: *mut c_uchar, - _recid: *mut c_int, _sig: *const RecoverableSignature) - -> c_int { - unimplemented!(); - } - - pub unsafe fn secp256k1_ecdsa_recoverable_signature_convert(_cx: *const Context, _sig: *mut Signature, - _input: *const RecoverableSignature) - -> c_int { - unimplemented!(); - } - - /// Sets sig to (2|3)||msg32||sk - pub unsafe fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, - sig: *mut RecoverableSignature, - msg32: *const c_uchar, - sk: *const c_uchar, - _noncefn: NonceFn, - _noncedata: *const c_void) - -> c_int { - assert!(!cx.is_null() && (*cx).flags() & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); - assert!((*cx).flags() & SECP256K1_START_SIGN == SECP256K1_START_SIGN); - if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } - if *sk.offset(0) > 0x7f { - (*sig).0[0] = 2; - } else { - (*sig).0[0] = 3; + /// Sets sig to msg32||full pk + pub unsafe fn secp256k1_ecdsa_sign_recoverable( + cx: *const Context, + sig: *mut RecoverableSignature, + msg32: *const c_uchar, + sk: *const c_uchar, + _noncefn: NonceFn, + _noncedata: *const c_void, + ) -> c_int { + // Check context is built for signing (and compute pk) + let mut new_pk = PublicKey::new(); + if secp256k1_ec_pubkey_create(cx, &mut new_pk, sk) != 1 { + return 0; } - ptr::copy(msg32, (*sig).0[1..33].as_mut_ptr(), 32); - ptr::copy(sk, (*sig).0[33..65].as_mut_ptr(), 32); + // Sign + let sig_sl = slice::from_raw_parts_mut(sig as *mut u8, 65); + let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); + sig_sl[..32].copy_from_slice(msg_sl); + let mut out_len: size_t = 33; + secp256k1_ec_pubkey_serialize(cx, sig_sl[32..].as_mut_ptr(), &mut out_len, &new_pk, SECP256K1_SER_COMPRESSED); + // Encode the parity of the pubkey in the final byte as 0/1, + // which is the same encoding (though the parity is computed + // differently) as real recoverable signatures. + sig_sl.swap(32, 64); + sig_sl[64] -= 2; 1 } - pub unsafe fn secp256k1_ecdsa_recover(_cx: *const Context, - _pk: *mut PublicKey, - _sig: *const RecoverableSignature, - _msg32: *const c_uchar) - -> c_int { - unimplemented!(); + pub unsafe fn secp256k1_ecdsa_recover( + cx: *const Context, + pk: *mut PublicKey, + sig: *const RecoverableSignature, + msg32: *const c_uchar + ) -> c_int { + let sig_sl = slice::from_raw_parts(sig as *const u8, 65); + let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); + println!("HMM0"); + + if sig_sl[64] > 4 { + return 0; + } + // Pull the original pk out of the siganture + let mut pk_ser = [0; 33]; + pk_ser.copy_from_slice(&sig_sl[32..]); + pk_ser.swap(0, 32); + pk_ser[0] += 2; + // Check that it parses (in a real sig, this would be the R value, + // so it is actually required to be a valid point) + if secp256k1_ec_pubkey_parse(cx, pk, pk_ser.as_ptr(), 33) == 0 { + return 0; + } + // Munge it up so that a different message will give a different pk + for i in 0..32 { + pk_ser[i + 1] ^= sig_sl[i] ^ msg_sl[i]; + } + // If any munging happened, this will fail parsing half the time, so + // tweak-and-loop until we find a key that works. + let mut idx = 0; + while secp256k1_ec_pubkey_parse(cx, pk, pk_ser.as_ptr(), 33) == 0 { + pk_ser[1 + idx / 8] ^= 1 << (idx % 8); + idx += 1; + } + 1 } } #[cfg(rust_secp_fuzz)] diff --git a/src/lib.rs b/src/lib.rs index b4eddd7..bfbb1eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,6 +103,7 @@ //! 0xc9, 0x42, 0x8f, 0xca, 0x69, 0xc1, 0x32, 0xa2, //! ]).expect("compact signatures are 64 bytes; DER signatures are 68-72 bytes"); //! +//! # #[cfg(not(rust_secp_fuzz))] //! assert!(secp.verify(&message, &sig, &public_key).is_ok()); //! ``` //! @@ -1221,6 +1222,7 @@ mod tests { } #[cfg(feature = "serde")] + #[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs #[test] fn test_signature_serde() { use serde_test::{Configure, Token, assert_tokens}; diff --git a/src/recovery.rs b/src/recovery.rs index 5eb6f57..e598ca8 100644 --- a/src/recovery.rs +++ b/src/recovery.rs @@ -235,6 +235,7 @@ mod tests { } #[test] + #[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs fn sign() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); diff --git a/src/schnorrsig.rs b/src/schnorrsig.rs index f637456..12ab2f2 100644 --- a/src/schnorrsig.rs +++ b/src/schnorrsig.rs @@ -722,6 +722,7 @@ mod tests { } #[cfg(feature = "serde")] + #[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs #[test] fn test_signature_serde() { use serde_test::{assert_tokens, Configure, Token}; From d1714ce0acfa0270419665a052be861b79a2e9e9 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Mon, 28 Dec 2020 18:55:33 +0000 Subject: [PATCH 4/5] fuzz: disable sig-grinding tests, prevent spin-looping --- src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index bfbb1eb..61d12c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -736,6 +736,10 @@ impl Secp256k1 { } entropy_p = extra_entropy.as_ptr() as *const ffi::types::c_void; + + // When fuzzing, these checks will usually spinloop forever, so just short-circuit them. + #[cfg(rust_secp_fuzz)] + return Signature::from(ret); } } } @@ -1098,9 +1102,12 @@ mod tests { if compact[0] < 0x80 { assert_eq!(sig, low_r_sig); } else { + #[cfg(not(rust_secp_fuzz))] // mocked sig generation doesn't produce low-R sigs assert_ne!(sig, low_r_sig); } + #[cfg(not(rust_secp_fuzz))] // mocked sig generation doesn't produce low-R sigs assert!(super::compact_sig_has_zero_first_bit(&low_r_sig.0)); + #[cfg(not(rust_secp_fuzz))] // mocked sig generation doesn't produce low-R sigs assert!(super::der_length_check(&grind_r_sig.0, 70)); } } @@ -1195,6 +1202,7 @@ mod tests { } #[test] + #[cfg(not(rust_secp_fuzz))] // fuzz-sigs have fixed size/format fn test_low_r() { let secp = Secp256k1::new(); let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac"); @@ -1209,6 +1217,7 @@ mod tests { } #[test] + #[cfg(not(rust_secp_fuzz))] // fuzz-sigs have fixed size/format fn test_grind_r() { let secp = Secp256k1::new(); let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167"); From 75d717729a1f8536a6da57c70442ec0fd3656cb7 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Mon, 28 Dec 2020 18:56:16 +0000 Subject: [PATCH 5/5] fuzz: fix elichai's nits --- contrib/test.sh | 4 ++-- secp256k1-sys/src/recovery.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/contrib/test.sh b/contrib/test.sh index 5f9203d..dd8430e 100755 --- a/contrib/test.sh +++ b/contrib/test.sh @@ -34,8 +34,8 @@ if [ "$DO_FEATURE_MATRIX" = true ]; then done # Other combos - RUSTFLAGS='--cfg=rust_secp_fuzz' cargo test --all - RUSTFLAGS='--cfg=rust_secp_fuzz' cargo test --all --features="$FEATURES" + RUSTFLAGS='--cfg=rust_secp_fuzz' RUSTDOCFLAGS=$RUSTFLAGS cargo test --all + RUSTFLAGS='--cfg=rust_secp_fuzz' RUSTDOCFLAGS=$RUSTFLAGS cargo test --all --features="$FEATURES" cargo test --all --features="rand rand-std" cargo test --all --features="rand serde" diff --git a/secp256k1-sys/src/recovery.rs b/secp256k1-sys/src/recovery.rs index 683eef4..dec4f73 100644 --- a/secp256k1-sys/src/recovery.rs +++ b/secp256k1-sys/src/recovery.rs @@ -118,9 +118,8 @@ mod fuzz_dummy { ) -> c_int { let sig_sl = slice::from_raw_parts(sig as *const u8, 65); let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); - println!("HMM0"); - if sig_sl[64] > 4 { + if sig_sl[64] >= 4 { return 0; } // Pull the original pk out of the siganture