Skip to content

Commit 02f6617

Browse files
authored
Merge pull request #179 from elichai/2019-11-raw-context
Creating context from raw pointer
2 parents cf22f60 + 9523e09 commit 02f6617

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

src/context.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::marker::PhantomData;
2+
use ptr;
23
use ffi::{self, CPtr};
34
use types::{c_uint, c_void};
45
use Error;
@@ -214,6 +215,25 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
214215
pub fn preallocate_size() -> usize {
215216
Self::preallocate_size_gen()
216217
}
218+
219+
/// Create a context from a raw context.
220+
///
221+
/// # Safety
222+
/// This is highly unsafe, due to the number of conditions that aren't checked.
223+
/// * `raw_ctx` needs to be a valid Secp256k1 context pointer.
224+
/// that was generated by *exactly* the same code/version of the libsecp256k1 used here.
225+
/// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1
226+
/// when generating the context.
227+
/// * The user must handle the freeing of the context(using the correct functions) by himself.
228+
/// * Violating these may lead to Undefined Behavior.
229+
///
230+
pub unsafe fn from_raw_all(raw_ctx: *mut ffi::Context) -> Secp256k1<AllPreallocated<'buf>> {
231+
Secp256k1 {
232+
ctx: raw_ctx,
233+
phantom: PhantomData,
234+
buf: ptr::null_mut::<[u8;0]>() as *mut [u8] ,
235+
}
236+
}
217237
}
218238

219239
impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
@@ -227,6 +247,25 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
227247
pub fn preallocate_signing_size() -> usize {
228248
Self::preallocate_size_gen()
229249
}
250+
251+
/// Create a context from a raw context.
252+
///
253+
/// # Safety
254+
/// This is highly unsafe, due to the number of conditions that aren't checked.
255+
/// * `raw_ctx` needs to be a valid Secp256k1 context pointer.
256+
/// that was generated by *exactly* the same code/version of the libsecp256k1 used here.
257+
/// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1
258+
/// when generating the context.
259+
/// * The user must handle the freeing of the context(using the correct functions) by himself.
260+
/// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior.,
261+
///
262+
pub unsafe fn from_raw_signining_only(raw_ctx: *mut ffi::Context) -> Secp256k1<SignOnlyPreallocated<'buf>> {
263+
Secp256k1 {
264+
ctx: raw_ctx,
265+
phantom: PhantomData,
266+
buf: ptr::null_mut::<[u8;0]>() as *mut [u8] ,
267+
}
268+
}
230269
}
231270

232271
impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
@@ -240,4 +279,23 @@ impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
240279
pub fn preallocate_verification_size() -> usize {
241280
Self::preallocate_size_gen()
242281
}
243-
}
282+
283+
/// Create a context from a raw context.
284+
///
285+
/// # Safety
286+
/// This is highly unsafe, due to the number of conditions that aren't checked.
287+
/// * `raw_ctx` needs to be a valid Secp256k1 context pointer.
288+
/// that was generated by *exactly* the same code/version of the libsecp256k1 used here.
289+
/// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1
290+
/// when generating the context.
291+
/// * The user must handle the freeing of the context(using the correct functions) by himself.
292+
/// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior.,
293+
///
294+
pub unsafe fn from_raw_verification_only(raw_ctx: *mut ffi::Context) -> Secp256k1<VerifyOnlyPreallocated<'buf>> {
295+
Secp256k1 {
296+
ctx: raw_ctx,
297+
phantom: PhantomData,
298+
buf: ptr::null_mut::<[u8;0]>() as *mut [u8] ,
299+
}
300+
}
301+
}

src/lib.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,41 @@ mod tests {
756756
unsafe { ffi::secp256k1_context_destroy(ctx_full) };
757757
}
758758

759+
#[test]
760+
fn test_raw_ctx() {
761+
let ctx_full = Secp256k1::new();
762+
let ctx_sign = Secp256k1::signing_only();
763+
let ctx_vrfy = Secp256k1::verification_only();
764+
765+
let full = unsafe {Secp256k1::from_raw_all(ctx_full.ctx)};
766+
let sign = unsafe {Secp256k1::from_raw_signining_only(ctx_sign.ctx)};
767+
let vrfy = unsafe {Secp256k1::from_raw_verification_only(ctx_vrfy.ctx)};
768+
769+
let (sk, pk) = full.generate_keypair(&mut thread_rng());
770+
let msg = Message::from_slice(&[2u8; 32]).unwrap();
771+
// Try signing
772+
assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk));
773+
let sig = full.sign(&msg, &sk);
774+
775+
// Try verifying
776+
assert!(vrfy.verify(&msg, &sig, &pk).is_ok());
777+
assert!(full.verify(&msg, &sig, &pk).is_ok());
778+
779+
drop(full);drop(sign);drop(vrfy);
780+
drop(ctx_full);drop(ctx_sign);drop(ctx_vrfy);
781+
}
782+
783+
#[test]
784+
#[should_panic]
785+
fn test_panic_raw_ctx() {
786+
let ctx_vrfy = Secp256k1::verification_only();
787+
let raw_ctx_verify_as_full = unsafe {Secp256k1::from_raw_all(ctx_vrfy.ctx)};
788+
let (sk, _) = raw_ctx_verify_as_full.generate_keypair(&mut thread_rng());
789+
let msg = Message::from_slice(&[2u8; 32]).unwrap();
790+
// Try signing
791+
raw_ctx_verify_as_full.sign(&msg, &sk);
792+
}
793+
759794
#[test]
760795
fn test_preallocation() {
761796
let mut buf_ful = vec![0u8; Secp256k1::preallocate_size()];

0 commit comments

Comments
 (0)