Merge pull request #151 from elichai/2019-08-Cptr-null
Explicit checks for ZST + null fallbacks
This commit is contained in:
commit
eddfe03dbc
|
@ -1,5 +1,5 @@
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use ffi;
|
use ffi::{self, CPtr};
|
||||||
use types::{c_uint, c_void};
|
use types::{c_uint, c_void};
|
||||||
use Error;
|
use Error;
|
||||||
use Secp256k1;
|
use Secp256k1;
|
||||||
|
@ -181,7 +181,7 @@ impl<'buf, C: Context + 'buf> Secp256k1<C> {
|
||||||
Ok(Secp256k1 {
|
Ok(Secp256k1 {
|
||||||
ctx: unsafe {
|
ctx: unsafe {
|
||||||
ffi::secp256k1_context_preallocated_create(
|
ffi::secp256k1_context_preallocated_create(
|
||||||
buf.as_mut_ptr() as *mut c_void,
|
buf.as_mut_c_ptr() as *mut c_void,
|
||||||
C::FLAGS)
|
C::FLAGS)
|
||||||
},
|
},
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
use core::{ops, ptr};
|
use core::{ops, ptr};
|
||||||
|
|
||||||
use key::{SecretKey, PublicKey};
|
use key::{SecretKey, PublicKey};
|
||||||
use ffi;
|
use ffi::{self, CPtr};
|
||||||
|
|
||||||
/// A tag used for recovering the public key from a compact signature
|
/// A tag used for recovering the public key from a compact signature
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
@ -34,8 +34,8 @@ impl SharedSecret {
|
||||||
let res = ffi::secp256k1_ecdh(
|
let res = ffi::secp256k1_ecdh(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut ss,
|
&mut ss,
|
||||||
point.as_ptr(),
|
point.as_c_ptr(),
|
||||||
scalar.as_ptr(),
|
scalar.as_c_ptr(),
|
||||||
ffi::secp256k1_ecdh_hash_function_default,
|
ffi::secp256k1_ecdh_hash_function_default,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
);
|
);
|
||||||
|
|
34
src/ffi.rs
34
src/ffi.rs
|
@ -16,7 +16,7 @@
|
||||||
//! # FFI bindings
|
//! # FFI bindings
|
||||||
//! Direct bindings to the underlying C library functions. These should
|
//! Direct bindings to the underlying C library functions. These should
|
||||||
//! not be needed for most users.
|
//! not be needed for most users.
|
||||||
use core::{mem, hash, slice};
|
use core::{mem, hash, slice, ptr};
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Flag for context to enable no precomputation
|
/// Flag for context to enable no precomputation
|
||||||
|
@ -359,6 +359,38 @@ unsafe fn strlen(mut str_ptr: *const c_char) -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A trait for producing pointers that will always be valid in C. (assuming NULL pointer is a valid no-op)
|
||||||
|
/// Rust doesn't promise what pointers does it give to ZST (https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
|
||||||
|
/// In case the type is empty this trait will give a NULL pointer, which should be handled in C.
|
||||||
|
///
|
||||||
|
pub(crate) trait CPtr {
|
||||||
|
type Target;
|
||||||
|
fn as_c_ptr(&self) -> *const Self::Target;
|
||||||
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> CPtr for [T] {
|
||||||
|
type Target = T;
|
||||||
|
fn as_c_ptr(&self) -> *const Self::Target {
|
||||||
|
if self.is_empty() {
|
||||||
|
ptr::null()
|
||||||
|
} else {
|
||||||
|
self.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
||||||
|
if self.is_empty() {
|
||||||
|
ptr::null::<Self::Target>() as *mut _
|
||||||
|
} else {
|
||||||
|
self.as_mut_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(feature = "fuzztarget")]
|
#[cfg(feature = "fuzztarget")]
|
||||||
mod fuzz_dummy {
|
mod fuzz_dummy {
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
78
src/key.rs
78
src/key.rs
|
@ -24,7 +24,7 @@ use super::Error::{self, InvalidPublicKey, InvalidSecretKey};
|
||||||
use Signing;
|
use Signing;
|
||||||
use Verification;
|
use Verification;
|
||||||
use constants;
|
use constants;
|
||||||
use ffi;
|
use ffi::{self, CPtr};
|
||||||
|
|
||||||
/// Secret 256-bit key used as `x` in an ECDSA signature
|
/// Secret 256-bit key used as `x` in an ECDSA signature
|
||||||
pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);
|
pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);
|
||||||
|
@ -117,7 +117,7 @@ impl SecretKey {
|
||||||
unsafe {
|
unsafe {
|
||||||
while ffi::secp256k1_ec_seckey_verify(
|
while ffi::secp256k1_ec_seckey_verify(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
data.as_ptr(),
|
data.as_c_ptr(),
|
||||||
) == 0
|
) == 0
|
||||||
{
|
{
|
||||||
data = random_32_bytes(rng);
|
data = random_32_bytes(rng);
|
||||||
|
@ -135,7 +135,7 @@ impl SecretKey {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_seckey_verify(
|
if ffi::secp256k1_ec_seckey_verify(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
data.as_ptr(),
|
data.as_c_ptr(),
|
||||||
) == 0
|
) == 0
|
||||||
{
|
{
|
||||||
return Err(InvalidSecretKey);
|
return Err(InvalidSecretKey);
|
||||||
|
@ -162,8 +162,8 @@ impl SecretKey {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_privkey_tweak_add(
|
if ffi::secp256k1_ec_privkey_tweak_add(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
self.as_mut_ptr(),
|
self.as_mut_c_ptr(),
|
||||||
other.as_ptr(),
|
other.as_c_ptr(),
|
||||||
) != 1
|
) != 1
|
||||||
{
|
{
|
||||||
Err(Error::InvalidTweak)
|
Err(Error::InvalidTweak)
|
||||||
|
@ -187,8 +187,8 @@ impl SecretKey {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_privkey_tweak_mul(
|
if ffi::secp256k1_ec_privkey_tweak_mul(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
self.as_mut_ptr(),
|
self.as_mut_c_ptr(),
|
||||||
other.as_ptr(),
|
other.as_c_ptr(),
|
||||||
) != 1
|
) != 1
|
||||||
{
|
{
|
||||||
Err(Error::InvalidTweak)
|
Err(Error::InvalidTweak)
|
||||||
|
@ -223,7 +223,7 @@ impl PublicKey {
|
||||||
unsafe {
|
unsafe {
|
||||||
// We can assume the return value because it's not possible to construct
|
// We can assume the return value because it's not possible to construct
|
||||||
// an invalid `SecretKey` without transmute trickery or something
|
// an invalid `SecretKey` without transmute trickery or something
|
||||||
let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_ptr());
|
let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_c_ptr());
|
||||||
debug_assert_eq!(res, 1);
|
debug_assert_eq!(res, 1);
|
||||||
}
|
}
|
||||||
PublicKey(pk)
|
PublicKey(pk)
|
||||||
|
@ -232,12 +232,14 @@ impl PublicKey {
|
||||||
/// Creates a public key directly from a slice
|
/// Creates a public key directly from a slice
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
|
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
|
||||||
|
if data.is_empty() {return Err(Error::InvalidPublicKey);}
|
||||||
|
|
||||||
let mut pk = ffi::PublicKey::new();
|
let mut pk = ffi::PublicKey::new();
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_pubkey_parse(
|
if ffi::secp256k1_ec_pubkey_parse(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut pk,
|
&mut pk,
|
||||||
data.as_ptr(),
|
data.as_c_ptr(),
|
||||||
data.len() as usize,
|
data.len() as usize,
|
||||||
) == 1
|
) == 1
|
||||||
{
|
{
|
||||||
|
@ -259,9 +261,9 @@ impl PublicKey {
|
||||||
let mut ret_len = constants::PUBLIC_KEY_SIZE as usize;
|
let mut ret_len = constants::PUBLIC_KEY_SIZE as usize;
|
||||||
let err = ffi::secp256k1_ec_pubkey_serialize(
|
let err = ffi::secp256k1_ec_pubkey_serialize(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
ret.as_mut_ptr(),
|
ret.as_mut_c_ptr(),
|
||||||
&mut ret_len,
|
&mut ret_len,
|
||||||
self.as_ptr(),
|
self.as_c_ptr(),
|
||||||
ffi::SECP256K1_SER_COMPRESSED,
|
ffi::SECP256K1_SER_COMPRESSED,
|
||||||
);
|
);
|
||||||
debug_assert_eq!(err, 1);
|
debug_assert_eq!(err, 1);
|
||||||
|
@ -278,9 +280,9 @@ impl PublicKey {
|
||||||
let mut ret_len = constants::UNCOMPRESSED_PUBLIC_KEY_SIZE as usize;
|
let mut ret_len = constants::UNCOMPRESSED_PUBLIC_KEY_SIZE as usize;
|
||||||
let err = ffi::secp256k1_ec_pubkey_serialize(
|
let err = ffi::secp256k1_ec_pubkey_serialize(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
ret.as_mut_ptr(),
|
ret.as_mut_c_ptr(),
|
||||||
&mut ret_len,
|
&mut ret_len,
|
||||||
self.as_ptr(),
|
self.as_c_ptr(),
|
||||||
ffi::SECP256K1_SER_UNCOMPRESSED,
|
ffi::SECP256K1_SER_UNCOMPRESSED,
|
||||||
);
|
);
|
||||||
debug_assert_eq!(err, 1);
|
debug_assert_eq!(err, 1);
|
||||||
|
@ -303,7 +305,7 @@ impl PublicKey {
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0 as *mut _,
|
if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0 as *mut _,
|
||||||
other.as_ptr()) == 1 {
|
other.as_c_ptr()) == 1 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidTweak)
|
Err(Error::InvalidTweak)
|
||||||
|
@ -325,7 +327,7 @@ impl PublicKey {
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0 as *mut _,
|
if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0 as *mut _,
|
||||||
other.as_ptr()) == 1 {
|
other.as_c_ptr()) == 1 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidTweak)
|
Err(Error::InvalidTweak)
|
||||||
|
@ -339,11 +341,11 @@ impl PublicKey {
|
||||||
pub fn combine(&self, other: &PublicKey) -> Result<PublicKey, Error> {
|
pub fn combine(&self, other: &PublicKey) -> Result<PublicKey, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret = ffi::PublicKey::new();
|
let mut ret = ffi::PublicKey::new();
|
||||||
let ptrs = [self.as_ptr(), other.as_ptr()];
|
let ptrs = [self.as_c_ptr(), other.as_c_ptr()];
|
||||||
if ffi::secp256k1_ec_pubkey_combine(
|
if ffi::secp256k1_ec_pubkey_combine(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
ptrs.as_ptr(),
|
ptrs.as_c_ptr(),
|
||||||
2
|
2
|
||||||
) == 1
|
) == 1
|
||||||
{
|
{
|
||||||
|
@ -355,6 +357,18 @@ impl PublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CPtr for PublicKey {
|
||||||
|
type Target = ffi::PublicKey;
|
||||||
|
fn as_c_ptr(&self) -> *const Self::Target {
|
||||||
|
self.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
||||||
|
self.as_mut_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Creates a new public key from a FFI public key
|
/// Creates a new public key from a FFI public key
|
||||||
impl From<ffi::PublicKey> for PublicKey {
|
impl From<ffi::PublicKey> for PublicKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -562,6 +576,36 @@ mod test {
|
||||||
PublicKey::from_slice(&[0x55; constants::PUBLIC_KEY_SIZE]),
|
PublicKey::from_slice(&[0x55; constants::PUBLIC_KEY_SIZE]),
|
||||||
Err(InvalidPublicKey)
|
Err(InvalidPublicKey)
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
PublicKey::from_slice(&[]),
|
||||||
|
Err(InvalidPublicKey)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_seckey_from_bad_slice() {
|
||||||
|
// Bad sizes
|
||||||
|
assert_eq!(
|
||||||
|
SecretKey::from_slice(&[0; constants::SECRET_KEY_SIZE - 1]),
|
||||||
|
Err(InvalidSecretKey)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
SecretKey::from_slice(&[0; constants::SECRET_KEY_SIZE + 1]),
|
||||||
|
Err(InvalidSecretKey)
|
||||||
|
);
|
||||||
|
// Bad parse
|
||||||
|
assert_eq!(
|
||||||
|
SecretKey::from_slice(&[0xff; constants::SECRET_KEY_SIZE]),
|
||||||
|
Err(InvalidSecretKey)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
SecretKey::from_slice(&[0x00; constants::SECRET_KEY_SIZE]),
|
||||||
|
Err(InvalidSecretKey)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
SecretKey::from_slice(&[]),
|
||||||
|
Err(InvalidSecretKey)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
40
src/lib.rs
40
src/lib.rs
|
@ -161,6 +161,7 @@ pub use key::PublicKey;
|
||||||
pub use context::*;
|
pub use context::*;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
use ffi::CPtr;
|
||||||
|
|
||||||
/// An ECDSA signature
|
/// An ECDSA signature
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
@ -246,13 +247,15 @@ impl Signature {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Converts a DER-encoded byte slice to a signature
|
/// Converts a DER-encoded byte slice to a signature
|
||||||
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
|
||||||
|
if data.is_empty() {return Err(Error::InvalidSignature);}
|
||||||
|
|
||||||
let mut ret = ffi::Signature::new();
|
let mut ret = ffi::Signature::new();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_signature_parse_der(
|
if ffi::secp256k1_ecdsa_signature_parse_der(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
data.as_ptr(),
|
data.as_c_ptr(),
|
||||||
data.len() as usize,
|
data.len() as usize,
|
||||||
) == 1
|
) == 1
|
||||||
{
|
{
|
||||||
|
@ -274,7 +277,7 @@ impl Signature {
|
||||||
if ffi::secp256k1_ecdsa_signature_parse_compact(
|
if ffi::secp256k1_ecdsa_signature_parse_compact(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
data.as_ptr(),
|
data.as_c_ptr(),
|
||||||
) == 1
|
) == 1
|
||||||
{
|
{
|
||||||
Ok(Signature(ret))
|
Ok(Signature(ret))
|
||||||
|
@ -289,12 +292,14 @@ impl Signature {
|
||||||
/// 2016. It should never be used in new applications. This library does not
|
/// 2016. It should never be used in new applications. This library does not
|
||||||
/// support serializing to this "format"
|
/// support serializing to this "format"
|
||||||
pub fn from_der_lax(data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_der_lax(data: &[u8]) -> Result<Signature, Error> {
|
||||||
|
if data.is_empty() {return Err(Error::InvalidSignature);}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret = ffi::Signature::new();
|
let mut ret = ffi::Signature::new();
|
||||||
if ffi::ecdsa_signature_parse_der_lax(
|
if ffi::ecdsa_signature_parse_der_lax(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
data.as_ptr(),
|
data.as_c_ptr(),
|
||||||
data.len() as usize,
|
data.len() as usize,
|
||||||
) == 1
|
) == 1
|
||||||
{
|
{
|
||||||
|
@ -328,8 +333,8 @@ impl Signature {
|
||||||
// was already normalized. We don't care.
|
// was already normalized. We don't care.
|
||||||
ffi::secp256k1_ecdsa_signature_normalize(
|
ffi::secp256k1_ecdsa_signature_normalize(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
self.as_mut_ptr(),
|
self.as_mut_c_ptr(),
|
||||||
self.as_ptr(),
|
self.as_c_ptr(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,7 +361,7 @@ impl Signature {
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
ret.get_data_mut_ptr(),
|
ret.get_data_mut_ptr(),
|
||||||
&mut len,
|
&mut len,
|
||||||
self.as_ptr(),
|
self.as_c_ptr(),
|
||||||
);
|
);
|
||||||
debug_assert!(err == 1);
|
debug_assert!(err == 1);
|
||||||
ret.set_len(len);
|
ret.set_len(len);
|
||||||
|
@ -371,8 +376,8 @@ impl Signature {
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_ecdsa_signature_serialize_compact(
|
let err = ffi::secp256k1_ecdsa_signature_serialize_compact(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
ret.as_mut_ptr(),
|
ret.as_mut_c_ptr(),
|
||||||
self.as_ptr(),
|
self.as_c_ptr(),
|
||||||
);
|
);
|
||||||
debug_assert!(err == 1);
|
debug_assert!(err == 1);
|
||||||
}
|
}
|
||||||
|
@ -380,6 +385,17 @@ impl Signature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CPtr for Signature {
|
||||||
|
type Target = ffi::Signature;
|
||||||
|
fn as_c_ptr(&self) -> *const Self::Target {
|
||||||
|
self.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
||||||
|
self.as_mut_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new signature from a FFI signature
|
/// Creates a new signature from a FFI signature
|
||||||
impl From<ffi::Signature> for Signature {
|
impl From<ffi::Signature> for Signature {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -583,7 +599,7 @@ impl<C: Context> Secp256k1<C> {
|
||||||
let mut seed = [0; 32];
|
let mut seed = [0; 32];
|
||||||
rng.fill_bytes(&mut seed);
|
rng.fill_bytes(&mut seed);
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_ptr());
|
let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_c_ptr());
|
||||||
// This function cannot fail; it has an error return for future-proofing.
|
// This function cannot fail; it has an error return for future-proofing.
|
||||||
// We do not expose this error since it is impossible to hit, and we have
|
// We do not expose this error since it is impossible to hit, and we have
|
||||||
// precedent for not exposing impossible errors (for example in
|
// precedent for not exposing impossible errors (for example in
|
||||||
|
@ -609,8 +625,8 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
unsafe {
|
unsafe {
|
||||||
// We can assume the return value because it's not possible to construct
|
// We can assume the return value because it's not possible to construct
|
||||||
// an invalid signature from a valid `Message` and `SecretKey`
|
// an invalid signature from a valid `Message` and `SecretKey`
|
||||||
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_ptr(),
|
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
|
||||||
sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979,
|
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
|
||||||
ptr::null()), 1);
|
ptr::null()), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,7 +656,7 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> {
|
pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), pk.as_ptr()) == 0 {
|
if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_c_ptr(), msg.as_c_ptr(), pk.as_c_ptr()) == 0 {
|
||||||
Err(Error::IncorrectSignature)
|
Err(Error::IncorrectSignature)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -122,6 +122,24 @@ macro_rules! impl_array_newtype {
|
||||||
&dat[..]
|
&dat[..]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl ::ffi::CPtr for $thing {
|
||||||
|
type Target = $ty;
|
||||||
|
fn as_c_ptr(&self) -> *const Self::Target {
|
||||||
|
if self.is_empty() {
|
||||||
|
::core::ptr::null()
|
||||||
|
} else {
|
||||||
|
self.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
||||||
|
if self.is_empty() {
|
||||||
|
::core::ptr::null::<Self::Target>() as *mut _
|
||||||
|
} else {
|
||||||
|
self.as_mut_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use types::*;
|
use types::*;
|
||||||
use ffi::{Context, NonceFn, PublicKey, Signature};
|
use ffi::{Context, NonceFn, PublicKey, Signature, CPtr};
|
||||||
|
|
||||||
/// Library-internal representation of a Secp256k1 signature + recovery ID
|
/// Library-internal representation of a Secp256k1 signature + recovery ID
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -23,6 +23,7 @@ use super::{Secp256k1, Message, Error, Signature, Verification, Signing};
|
||||||
use super::ffi as super_ffi;
|
use super::ffi as super_ffi;
|
||||||
pub use key::SecretKey;
|
pub use key::SecretKey;
|
||||||
pub use key::PublicKey;
|
pub use key::PublicKey;
|
||||||
|
use self::super_ffi::CPtr;
|
||||||
|
|
||||||
mod ffi;
|
mod ffi;
|
||||||
|
|
||||||
|
@ -57,6 +58,8 @@ impl RecoverableSignature {
|
||||||
/// representation is nonstandard and defined by the libsecp256k1
|
/// representation is nonstandard and defined by the libsecp256k1
|
||||||
/// library.
|
/// library.
|
||||||
pub fn from_compact(data: &[u8], recid: RecoveryId) -> Result<RecoverableSignature, Error> {
|
pub fn from_compact(data: &[u8], recid: RecoveryId) -> Result<RecoverableSignature, Error> {
|
||||||
|
if data.is_empty() {return Err(Error::InvalidSignature);}
|
||||||
|
|
||||||
let mut ret = ffi::RecoverableSignature::new();
|
let mut ret = ffi::RecoverableSignature::new();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -65,7 +68,7 @@ impl RecoverableSignature {
|
||||||
} else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact(
|
} else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact(
|
||||||
super_ffi::secp256k1_context_no_precomp,
|
super_ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
data.as_ptr(),
|
data.as_c_ptr(),
|
||||||
recid.0,
|
recid.0,
|
||||||
) == 1
|
) == 1
|
||||||
{
|
{
|
||||||
|
@ -82,6 +85,12 @@ impl RecoverableSignature {
|
||||||
&self.0 as *const _
|
&self.0 as *const _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
||||||
|
#[inline]
|
||||||
|
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature {
|
||||||
|
&mut self.0 as *mut _
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Serializes the recoverable signature in compact format
|
/// Serializes the recoverable signature in compact format
|
||||||
pub fn serialize_compact(&self) -> (RecoveryId, [u8; 64]) {
|
pub fn serialize_compact(&self) -> (RecoveryId, [u8; 64]) {
|
||||||
|
@ -90,9 +99,9 @@ impl RecoverableSignature {
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
let err = ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
||||||
super_ffi::secp256k1_context_no_precomp,
|
super_ffi::secp256k1_context_no_precomp,
|
||||||
ret.as_mut_ptr(),
|
ret.as_mut_c_ptr(),
|
||||||
&mut recid,
|
&mut recid,
|
||||||
self.as_ptr(),
|
self.as_c_ptr(),
|
||||||
);
|
);
|
||||||
assert!(err == 1);
|
assert!(err == 1);
|
||||||
}
|
}
|
||||||
|
@ -108,7 +117,7 @@ impl RecoverableSignature {
|
||||||
let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(
|
let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(
|
||||||
super_ffi::secp256k1_context_no_precomp,
|
super_ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
self.as_ptr(),
|
self.as_c_ptr(),
|
||||||
);
|
);
|
||||||
assert!(err == 1);
|
assert!(err == 1);
|
||||||
}
|
}
|
||||||
|
@ -116,6 +125,18 @@ impl RecoverableSignature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl CPtr for RecoverableSignature {
|
||||||
|
type Target = ffi::RecoverableSignature;
|
||||||
|
fn as_c_ptr(&self) -> *const Self::Target {
|
||||||
|
self.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
||||||
|
self.as_mut_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new recoverable signature from a FFI one
|
/// Creates a new recoverable signature from a FFI one
|
||||||
impl From<ffi::RecoverableSignature> for RecoverableSignature {
|
impl From<ffi::RecoverableSignature> for RecoverableSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -138,8 +159,8 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
ffi::secp256k1_ecdsa_sign_recoverable(
|
ffi::secp256k1_ecdsa_sign_recoverable(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
msg.as_ptr(),
|
msg.as_c_ptr(),
|
||||||
sk.as_ptr(),
|
sk.as_c_ptr(),
|
||||||
super_ffi::secp256k1_nonce_function_rfc6979,
|
super_ffi::secp256k1_nonce_function_rfc6979,
|
||||||
ptr::null()
|
ptr::null()
|
||||||
),
|
),
|
||||||
|
@ -161,7 +182,7 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk,
|
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk,
|
||||||
sig.as_ptr(), msg.as_ptr()) != 1 {
|
sig.as_c_ptr(), msg.as_c_ptr()) != 1 {
|
||||||
return Err(Error::InvalidSignature);
|
return Err(Error::InvalidSignature);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue