Skip to content

Commit 68896be

Browse files
committed
Safe array type macro impl for secret-key containing types
1 parent 7042eda commit 68896be

File tree

3 files changed

+69
-53
lines changed

3 files changed

+69
-53
lines changed

secp256k1-sys/src/macros.rs

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,23 @@
1313
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
1414
//
1515

16-
// This is a macro that routinely comes in handy
16+
/// Implements array accessing methods for a type that must be considered safe
1717
#[macro_export]
18-
macro_rules! impl_array_newtype {
18+
macro_rules! impl_safe_array_newtype {
1919
($thing:ident, $ty:ty, $len:expr) => {
20-
impl Copy for $thing {}
21-
2220
impl $thing {
2321
#[inline]
22+
#[allow(unused)]
2423
/// Converts the object to a raw pointer for FFI interfacing
25-
pub fn as_ptr(&self) -> *const $ty {
24+
pub(crate) fn as_ptr(&self) -> *const $ty {
2625
let &$thing(ref dat) = self;
2726
dat.as_ptr()
2827
}
2928

3029
#[inline]
30+
#[allow(unused)]
3131
/// Converts the object to a mutable raw pointer for FFI interfacing
32-
pub fn as_mut_ptr(&mut self) -> *mut $ty {
32+
pub(crate) fn as_mut_ptr(&mut self) -> *mut $ty {
3333
let &mut $thing(ref mut dat) = self;
3434
dat.as_mut_ptr()
3535
}
@@ -43,6 +43,47 @@ macro_rules! impl_array_newtype {
4343
pub fn is_empty(&self) -> bool { false }
4444
}
4545

46+
impl $crate::CPtr for $thing {
47+
type Target = $ty;
48+
49+
fn as_c_ptr(&self) -> *const Self::Target {
50+
if self.is_empty() {
51+
::core::ptr::null()
52+
} else {
53+
let &$thing(ref dat) = self;
54+
dat.as_ptr()
55+
}
56+
}
57+
58+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
59+
if self.is_empty() {
60+
::core::ptr::null::<Self::Target>() as *mut _
61+
} else {
62+
let &mut $thing(ref mut dat) = self;
63+
dat.as_mut_ptr()
64+
}
65+
}
66+
}
67+
}
68+
}
69+
70+
/// Generates implementation of main array accessing methods for a newtype wrapping some inner array
71+
/// type
72+
#[macro_export]
73+
macro_rules! impl_array_newtype {
74+
($thing:ident, $ty:ty, $len:expr) => {
75+
impl_safe_array_newtype!($thing, $ty, $len);
76+
77+
impl Copy for $thing {}
78+
79+
impl Clone for $thing {
80+
#[inline]
81+
fn clone(&self) -> $thing {
82+
let &$thing(ref dat) = self;
83+
$thing(dat.clone())
84+
}
85+
}
86+
4687
impl AsRef<[$ty; $len]> for $thing {
4788
#[inline]
4889
/// Gets a reference to the underlying array
@@ -55,7 +96,7 @@ macro_rules! impl_array_newtype {
5596
impl PartialEq for $thing {
5697
#[inline]
5798
fn eq(&self, other: &$thing) -> bool {
58-
&self[..] == &other[..]
99+
&self.0[..] == &other[..]
59100
}
60101
}
61102

@@ -75,14 +116,6 @@ macro_rules! impl_array_newtype {
75116
}
76117
}
77118

78-
impl Clone for $thing {
79-
#[inline]
80-
fn clone(&self) -> $thing {
81-
let &$thing(ref dat) = self;
82-
$thing(dat.clone())
83-
}
84-
}
85-
86119
impl ::core::ops::Index<usize> for $thing {
87120
type Output = $ty;
88121

@@ -132,24 +165,6 @@ macro_rules! impl_array_newtype {
132165
&dat[..]
133166
}
134167
}
135-
impl $crate::CPtr for $thing {
136-
type Target = $ty;
137-
fn as_c_ptr(&self) -> *const Self::Target {
138-
if self.is_empty() {
139-
::core::ptr::null()
140-
} else {
141-
self.as_ptr()
142-
}
143-
}
144-
145-
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
146-
if self.is_empty() {
147-
::core::ptr::null::<Self::Target>() as *mut _
148-
} else {
149-
self.as_mut_ptr()
150-
}
151-
}
152-
}
153168
}
154169
}
155170

src/key.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ use constants;
2727
use ffi::{self, CPtr};
2828

2929
/// Secret 256-bit key used as `x` in an ECDSA signature
30+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
3031
pub struct SecretKey(pub(crate) [u8; constants::SECRET_KEY_SIZE]);
31-
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
32+
impl_safe_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
3233
impl_safe_debug!(SecretKey);
3334

3435
impl fmt::LowerHex for SecretKey {
@@ -220,7 +221,7 @@ impl ::serde::Serialize for SecretKey {
220221
if s.is_human_readable() {
221222
s.collect_str(self)
222223
} else {
223-
s.serialize_bytes(&self[..])
224+
s.serialize_bytes(&self.0[..])
224225
}
225226
}
226227
}
@@ -529,7 +530,7 @@ mod test {
529530
let s = Secp256k1::new();
530531

531532
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
532-
assert_eq!(SecretKey::from_slice(&sk1[..]), Ok(sk1));
533+
assert_eq!(SecretKey::from_slice(&sk1.0[..]), Ok(sk1));
533534
assert_eq!(PublicKey::from_slice(&pk1.serialize()[..]), Ok(pk1));
534535
assert_eq!(PublicKey::from_slice(&pk1.serialize_uncompressed()[..]), Ok(pk1));
535536
}
@@ -784,13 +785,13 @@ mod test {
784785
let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng());
785786

786787
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
787-
assert!(sk1.add_assign(&sk2[..]).is_ok());
788-
assert!(pk1.add_exp_assign(&s, &sk2[..]).is_ok());
788+
assert!(sk1.add_assign(&sk2.0[..]).is_ok());
789+
assert!(pk1.add_exp_assign(&s, &sk2.0[..]).is_ok());
789790
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
790791

791792
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
792-
assert!(sk2.add_assign(&sk1[..]).is_ok());
793-
assert!(pk2.add_exp_assign(&s, &sk1[..]).is_ok());
793+
assert!(sk2.add_assign(&sk1.0[..]).is_ok());
794+
assert!(pk2.add_exp_assign(&s, &sk1.0[..]).is_ok());
794795
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
795796
}
796797

@@ -802,13 +803,13 @@ mod test {
802803
let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng());
803804

804805
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
805-
assert!(sk1.mul_assign(&sk2[..]).is_ok());
806-
assert!(pk1.mul_assign(&s, &sk2[..]).is_ok());
806+
assert!(sk1.mul_assign(&sk2.0[..]).is_ok());
807+
assert!(pk1.mul_assign(&s, &sk2.0[..]).is_ok());
807808
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
808809

809810
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
810-
assert!(sk2.mul_assign(&sk1[..]).is_ok());
811-
assert!(pk2.mul_assign(&s, &sk1[..]).is_ok());
811+
assert!(sk2.mul_assign(&sk1.0[..]).is_ok());
812+
assert!(pk2.mul_assign(&s, &sk1.0[..]).is_ok());
812813
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
813814
}
814815

@@ -818,7 +819,7 @@ mod test {
818819

819820
let (mut sk, mut pk) = s.generate_keypair(&mut thread_rng());
820821

821-
let original_sk = sk;
822+
let original_sk = sk.clone();
822823
let original_pk = pk;
823824

824825
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk);
@@ -913,7 +914,7 @@ mod test {
913914
assert!(sum2.is_ok());
914915
assert_eq!(sum1, sum2);
915916

916-
assert!(sk1.add_assign(&sk2.as_ref()[..]).is_ok());
917+
assert!(sk1.add_assign(&sk2.0[..]).is_ok());
917918
let sksum = PublicKey::from_secret_key(&s, &sk1);
918919
assert_eq!(Ok(sksum), sum1);
919920
}
@@ -974,13 +975,13 @@ mod test {
974975
#[cfg(fuzzing)]
975976
let pk = PublicKey::from_slice(&PK_BYTES).expect("pk");
976977

977-
assert_tokens(&sk.compact(), &[Token::BorrowedBytes(&SK_BYTES[..])]);
978-
assert_tokens(&sk.compact(), &[Token::Bytes(&SK_BYTES)]);
979-
assert_tokens(&sk.compact(), &[Token::ByteBuf(&SK_BYTES)]);
978+
assert_tokens(&sk.clone().compact(), &[Token::BorrowedBytes(&SK_BYTES[..])]);
979+
assert_tokens(&sk.clone().compact(), &[Token::Bytes(&SK_BYTES)]);
980+
assert_tokens(&sk.clone().compact(), &[Token::ByteBuf(&SK_BYTES)]);
980981

981-
assert_tokens(&sk.readable(), &[Token::BorrowedStr(SK_STR)]);
982-
assert_tokens(&sk.readable(), &[Token::Str(SK_STR)]);
983-
assert_tokens(&sk.readable(), &[Token::String(SK_STR)]);
982+
assert_tokens(&sk.clone().readable(), &[Token::BorrowedStr(SK_STR)]);
983+
assert_tokens(&sk.clone().readable(), &[Token::Str(SK_STR)]);
984+
assert_tokens(&sk.clone().readable(), &[Token::String(SK_STR)]);
984985

985986
assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]);
986987
assert_tokens(&pk.compact(), &[Token::Bytes(&PK_BYTES)]);

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ mod tests {
995995
assert!(full.verify(&msg, &sig, &pk).is_ok());
996996

997997
// Check that we can produce keys from slices with no precomputation
998-
let (pk_slice, sk_slice) = (&pk.serialize(), &sk[..]);
998+
let (pk_slice, sk_slice) = (&pk.serialize(), &sk.0[..]);
999999
let new_pk = PublicKey::from_slice(pk_slice).unwrap();
10001000
let new_sk = SecretKey::from_slice(sk_slice).unwrap();
10011001
assert_eq!(sk, new_sk);

0 commit comments

Comments
 (0)