16
16
//! # FFI of the recovery module
17
17
18
18
use :: types:: * ;
19
- #[ cfg( not( rust_secp_fuzz) ) ]
20
- use :: { Context , Signature , NonceFn , PublicKey } ;
19
+ use { Context , Signature , NonceFn , PublicKey } ;
21
20
22
21
/// Library-internal representation of a Secp256k1 signature + recovery ID
23
22
#[ repr( C ) ]
@@ -36,7 +35,6 @@ impl Default for RecoverableSignature {
36
35
}
37
36
}
38
37
39
- #[ cfg( not( rust_secp_fuzz) ) ]
40
38
extern "C" {
41
39
#[ cfg_attr( not( rust_secp_no_symbol_renaming) , link_name = "rustsecp256k1_v0_3_1_ecdsa_recoverable_signature_parse_compact" ) ]
42
40
pub fn secp256k1_ecdsa_recoverable_signature_parse_compact ( cx : * const Context , sig : * mut RecoverableSignature ,
@@ -52,6 +50,10 @@ extern "C" {
52
50
pub fn secp256k1_ecdsa_recoverable_signature_convert ( cx : * const Context , sig : * mut Signature ,
53
51
input : * const RecoverableSignature )
54
52
-> c_int ;
53
+ }
54
+
55
+ #[ cfg( not( rust_secp_fuzz) ) ]
56
+ extern "C" {
55
57
#[ cfg_attr( not( rust_secp_no_symbol_renaming) , link_name = "rustsecp256k1_v0_3_1_ecdsa_sign_recoverable" ) ]
56
58
pub fn secp256k1_ecdsa_sign_recoverable ( cx : * const Context ,
57
59
sig : * mut RecoverableSignature ,
@@ -72,58 +74,77 @@ extern "C" {
72
74
73
75
#[ cfg( rust_secp_fuzz) ]
74
76
mod fuzz_dummy {
75
- extern crate std;
76
- use self :: std:: ptr;
77
- use super :: RecoverableSignature ;
78
- use types:: * ;
79
- use :: { Signature , Context , PublicKey , NonceFn , secp256k1_ec_seckey_verify,
80
- SECP256K1_START_NONE , SECP256K1_START_VERIFY , SECP256K1_START_SIGN } ;
81
-
82
- pub unsafe fn secp256k1_ecdsa_recoverable_signature_parse_compact ( _cx : * const Context , _sig : * mut RecoverableSignature ,
83
- _input64 : * const c_uchar , _recid : c_int )
84
- -> c_int {
85
- unimplemented ! ( ) ;
86
- }
87
-
88
- pub unsafe fn secp256k1_ecdsa_recoverable_signature_serialize_compact ( _cx : * const Context , _output64 : * mut c_uchar ,
89
- _recid : * mut c_int , _sig : * const RecoverableSignature )
90
- -> c_int {
91
- unimplemented ! ( ) ;
92
- }
93
-
94
- pub unsafe fn secp256k1_ecdsa_recoverable_signature_convert ( _cx : * const Context , _sig : * mut Signature ,
95
- _input : * const RecoverableSignature )
96
- -> c_int {
97
- unimplemented ! ( ) ;
98
- }
99
-
100
- /// Sets sig to (2|3)||msg32||sk
101
- pub unsafe fn secp256k1_ecdsa_sign_recoverable ( cx : * const Context ,
102
- sig : * mut RecoverableSignature ,
103
- msg32 : * const c_uchar ,
104
- sk : * const c_uchar ,
105
- _noncefn : NonceFn ,
106
- _noncedata : * const c_void )
107
- -> c_int {
108
- assert ! ( !cx. is_null( ) && ( * cx) . flags( ) & !( SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN ) == 0 ) ;
109
- assert ! ( ( * cx) . flags( ) & SECP256K1_START_SIGN == SECP256K1_START_SIGN ) ;
110
- if secp256k1_ec_seckey_verify ( cx, sk) != 1 { return 0 ; }
111
- if * sk. offset ( 0 ) > 0x7f {
112
- ( * sig) . 0 [ 0 ] = 2 ;
113
- } else {
114
- ( * sig) . 0 [ 0 ] = 3 ;
77
+ use super :: * ;
78
+ use std:: slice;
79
+
80
+ use secp256k1_ec_pubkey_create;
81
+ use secp256k1_ec_pubkey_parse;
82
+ use secp256k1_ec_pubkey_serialize;
83
+ use SECP256K1_SER_COMPRESSED ;
84
+
85
+ /// Sets sig to msg32||full pk
86
+ pub unsafe fn secp256k1_ecdsa_sign_recoverable (
87
+ cx : * const Context ,
88
+ sig : * mut RecoverableSignature ,
89
+ msg32 : * const c_uchar ,
90
+ sk : * const c_uchar ,
91
+ _noncefn : NonceFn ,
92
+ _noncedata : * const c_void ,
93
+ ) -> c_int {
94
+ // Check context is built for signing (and compute pk)
95
+ let mut new_pk = PublicKey :: new ( ) ;
96
+ if secp256k1_ec_pubkey_create ( cx, & mut new_pk, sk) != 1 {
97
+ return 0 ;
115
98
}
116
- ptr:: copy ( msg32, ( * sig) . 0 [ 1 ..33 ] . as_mut_ptr ( ) , 32 ) ;
117
- ptr:: copy ( sk, ( * sig) . 0 [ 33 ..65 ] . as_mut_ptr ( ) , 32 ) ;
99
+ // Sign
100
+ let sig_sl = slice:: from_raw_parts_mut ( sig as * mut u8 , 65 ) ;
101
+ let msg_sl = slice:: from_raw_parts ( msg32 as * const u8 , 32 ) ;
102
+ sig_sl[ ..32 ] . copy_from_slice ( msg_sl) ;
103
+ let mut out_len: size_t = 33 ;
104
+ secp256k1_ec_pubkey_serialize ( cx, sig_sl[ 32 ..] . as_mut_ptr ( ) , & mut out_len, & new_pk, SECP256K1_SER_COMPRESSED ) ;
105
+ // Encode the parity of the pubkey in the final byte as 0/1,
106
+ // which is the same encoding (though the parity is computed
107
+ // differently) as real recoverable signatures.
108
+ sig_sl. swap ( 32 , 64 ) ;
109
+ sig_sl[ 64 ] -= 2 ;
118
110
1
119
111
}
120
112
121
- pub unsafe fn secp256k1_ecdsa_recover ( _cx : * const Context ,
122
- _pk : * mut PublicKey ,
123
- _sig : * const RecoverableSignature ,
124
- _msg32 : * const c_uchar )
125
- -> c_int {
126
- unimplemented ! ( ) ;
113
+ pub unsafe fn secp256k1_ecdsa_recover (
114
+ cx : * const Context ,
115
+ pk : * mut PublicKey ,
116
+ sig : * const RecoverableSignature ,
117
+ msg32 : * const c_uchar
118
+ ) -> c_int {
119
+ let sig_sl = slice:: from_raw_parts ( sig as * const u8 , 65 ) ;
120
+ let msg_sl = slice:: from_raw_parts ( msg32 as * const u8 , 32 ) ;
121
+ println ! ( "HMM0" ) ;
122
+
123
+ if sig_sl[ 64 ] > 4 {
124
+ return 0 ;
125
+ }
126
+ // Pull the original pk out of the siganture
127
+ let mut pk_ser = [ 0 ; 33 ] ;
128
+ pk_ser. copy_from_slice ( & sig_sl[ 32 ..] ) ;
129
+ pk_ser. swap ( 0 , 32 ) ;
130
+ pk_ser[ 0 ] += 2 ;
131
+ // Check that it parses (in a real sig, this would be the R value,
132
+ // so it is actually required to be a valid point)
133
+ if secp256k1_ec_pubkey_parse ( cx, pk, pk_ser. as_ptr ( ) , 33 ) == 0 {
134
+ return 0 ;
135
+ }
136
+ // Munge it up so that a different message will give a different pk
137
+ for i in 0 ..32 {
138
+ pk_ser[ i + 1 ] ^= sig_sl[ i] ^ msg_sl[ i] ;
139
+ }
140
+ // If any munging happened, this will fail parsing half the time, so
141
+ // tweak-and-loop until we find a key that works.
142
+ let mut idx = 0 ;
143
+ while secp256k1_ec_pubkey_parse ( cx, pk, pk_ser. as_ptr ( ) , 33 ) == 0 {
144
+ pk_ser[ 1 + idx / 8 ] ^= 1 << ( idx % 8 ) ;
145
+ idx += 1 ;
146
+ }
147
+ 1
127
148
}
128
149
}
129
150
#[ cfg( rust_secp_fuzz) ]
0 commit comments