@@ -29,17 +29,18 @@ pub mod global {
29
29
/// A global, static context to avoid repeatedly creating contexts where one can't be passed
30
30
///
31
31
/// If the global-context feature is enabled (and not just the global-context-less-secure),
32
- /// this will have been randomized.
32
+ /// this will have been randomized for additional defense-in-depth side channel protection .
33
33
pub static SECP256K1 : & GlobalContext = & GlobalContext { __private : ( ) } ;
34
34
35
35
impl Deref for GlobalContext {
36
36
type Target = Secp256k1 < All > ;
37
37
38
+ #[ allow( unused_mut) ] // mut is unused when "global-context" is not enabled.
38
39
fn deref ( & self ) -> & Self :: Target {
39
40
static ONCE : Once = Once :: new ( ) ;
40
41
static mut CONTEXT : Option < Secp256k1 < All > > = None ;
41
42
ONCE . call_once ( || unsafe {
42
- let mut ctx = Secp256k1 :: new ( ) ;
43
+ let mut ctx = Secp256k1 :: new ( SideChannelProtection :: NoRandomize ) ;
43
44
#[ cfg( feature = "global-context" ) ]
44
45
{
45
46
ctx. randomize ( & mut rand:: thread_rng ( ) ) ;
@@ -166,46 +167,57 @@ mod alloc_only {
166
167
}
167
168
168
169
impl < C : Context > Secp256k1 < C > {
169
- /// Lets you create a context in a generic manner(sign/verify/all)
170
- pub fn gen_new ( ) -> Secp256k1 < C > {
170
+ /// Lets you create a context in a generic manner(sign/verify/all).
171
+ ///
172
+ /// If the `rand` feature is enabled we randomize the context using `thread_rng`.
173
+ pub fn gen_new ( opt : SideChannelProtection ) -> Secp256k1 < C > {
171
174
#[ cfg( target_arch = "wasm32" ) ]
172
175
ffi:: types:: sanity_checks_for_wasm ( ) ;
173
176
174
177
let size = unsafe { ffi:: secp256k1_context_preallocated_size ( C :: FLAGS ) } ;
175
178
let layout = alloc:: Layout :: from_size_align ( size, ALIGN_TO ) . unwrap ( ) ;
176
179
let ptr = unsafe { alloc:: alloc ( layout) } ;
177
- Secp256k1 {
180
+ let mut secp = Secp256k1 {
178
181
ctx : unsafe { ffi:: secp256k1_context_preallocated_create ( ptr as * mut c_void , C :: FLAGS ) } ,
179
182
phantom : PhantomData ,
180
183
size,
184
+ } ;
185
+
186
+ match opt {
187
+ SideChannelProtection :: SeededRandomize ( seed) => secp. seeded_randomize ( seed) ,
188
+ SideChannelProtection :: NoRandomize => { } ,
189
+ #[ cfg( feature = "rand" ) ]
190
+ SideChannelProtection :: Randomize => secp. randomize ( & mut rand:: thread_rng ( ) ) ,
181
191
}
192
+
193
+ secp
182
194
}
183
195
}
184
196
185
197
impl Secp256k1 < All > {
186
- /// Creates a new Secp256k1 context with all capabilities
187
- pub fn new ( ) -> Secp256k1 < All > {
188
- Secp256k1 :: gen_new ( )
198
+ /// Creates a new Secp256k1 context with all capabilities.
199
+ ///
200
+ /// If the `rand` feature is enabled we randomize the context using `thread_rng`.
201
+ pub fn new ( opt : SideChannelProtection ) -> Secp256k1 < All > {
202
+ Secp256k1 :: gen_new ( opt)
189
203
}
190
204
}
191
205
192
206
impl Secp256k1 < SignOnly > {
193
- /// Creates a new Secp256k1 context that can only be used for signing
194
- pub fn signing_only ( ) -> Secp256k1 < SignOnly > {
195
- Secp256k1 :: gen_new ( )
207
+ /// Creates a new Secp256k1 context that can only be used for signing.
208
+ ///
209
+ /// If the `rand` feature is enabled we randomize the context using `thread_rng`.
210
+ pub fn signing_only ( opt : SideChannelProtection ) -> Secp256k1 < SignOnly > {
211
+ Secp256k1 :: gen_new ( opt)
196
212
}
197
213
}
198
214
199
215
impl Secp256k1 < VerifyOnly > {
200
- /// Creates a new Secp256k1 context that can only be used for verification
201
- pub fn verification_only ( ) -> Secp256k1 < VerifyOnly > {
202
- Secp256k1 :: gen_new ( )
203
- }
204
- }
205
-
206
- impl Default for Secp256k1 < All > {
207
- fn default ( ) -> Self {
208
- Self :: new ( )
216
+ /// Creates a new Secp256k1 context that can only be used for verification.
217
+ ///
218
+ /// If the `rand` feature is enabled we randomize the context using `thread_rng`.
219
+ pub fn verification_only ( opt : SideChannelProtection ) -> Secp256k1 < VerifyOnly > {
220
+ Secp256k1 :: gen_new ( opt)
209
221
}
210
222
}
211
223
@@ -221,6 +233,40 @@ mod alloc_only {
221
233
}
222
234
}
223
235
}
236
+
237
+ /// When initializing the context we support additional defense-in-depth side channel
238
+ /// protection, which re-blinds certain operations on secret key data.
239
+ ///
240
+ /// # Examples
241
+ ///
242
+ /// If your application already depends on `rand` and/or you do not wish to use the re-exported
243
+ /// secp2561 version of `rand` i.e., no transient dependency on `rand`.
244
+ ///```
245
+ /// use rand::thread_rng();
246
+ /// use secp256k1::Secp256k1;
247
+ ///
248
+ /// let mut rng = thread_rng().unwrap();
249
+ /// let mut seed = [0u8; 32];
250
+ /// rng.fill_bytes(&mut seed);
251
+ ///
252
+ /// let _ = Secp256k1::new(SeededRandomize(&seed));
253
+ /// ```
254
+ /// If you are ok with adding the transient dependency on `rand` from secp256k1.
255
+ /// ```
256
+ /// use secp256k1::Secp256k1;
257
+ ///
258
+ /// let _ = Secp256k1::new(Randomize);
259
+ /// ```
260
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug , PartialOrd , Ord , Hash ) ]
261
+ pub enum SideChannelProtection < ' a > { // FIXME: Does this name overstate the side channel risk?
262
+ /// Uses seed to randomize context (calls `seeded_randomize(seed)`).
263
+ SeededRandomize ( & ' a [ u8 ; 32 ] ) ,
264
+ /// Disables randomization (additional defense-in-depth sidechannel protection).
265
+ NoRandomize ,
266
+ /// Uses thread_rng to randomize context (calls `secp.randomize()`).
267
+ #[ cfg( feature = "rand" ) ]
268
+ Randomize ,
269
+ }
224
270
}
225
271
226
272
impl < ' buf > Signing for SignOnlyPreallocated < ' buf > { }
0 commit comments