From 5f8096e8a83f9d42ed671ddf5eb693cb3ea0eaf6 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 6 Nov 2019 16:15:22 +0200 Subject: [PATCH 1/2] Add functions to create from raw context --- src/context.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index e8eba5d..15379f5 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,4 +1,5 @@ use core::marker::PhantomData; +use ptr; use ffi::{self, CPtr}; use types::{c_uint, c_void}; use Error; @@ -199,6 +200,25 @@ impl<'buf> Secp256k1> { pub fn preallocate_size() -> usize { Self::preallocate_size_gen() } + + /// Create a context from a raw context. + /// + /// # Safety + /// This is highly unsafe, due to the number of conditions that aren't checked. + /// * `raw_ctx` needs to be a valid Secp256k1 context pointer. + /// that was generated by *exactly* the same code/version of the libsecp256k1 used here. + /// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1 + /// when generating the context. + /// * The user must handle the freeing of the context(using the correct functions) by himself. + /// * Violating these may lead to Undefined Behavior. + /// + pub unsafe fn from_raw_all(raw_ctx: *mut ffi::Context) -> Secp256k1> { + Secp256k1 { + ctx: raw_ctx, + phantom: PhantomData, + buf: ptr::null_mut::<[u8;0]>() as *mut [u8] , + } + } } impl<'buf> Secp256k1> { @@ -212,6 +232,25 @@ impl<'buf> Secp256k1> { pub fn preallocate_signing_size() -> usize { Self::preallocate_size_gen() } + + /// Create a context from a raw context. + /// + /// # Safety + /// This is highly unsafe, due to the number of conditions that aren't checked. + /// * `raw_ctx` needs to be a valid Secp256k1 context pointer. + /// that was generated by *exactly* the same code/version of the libsecp256k1 used here. + /// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1 + /// when generating the context. + /// * The user must handle the freeing of the context(using the correct functions) by himself. + /// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior., + /// + pub unsafe fn from_raw_signining_only(raw_ctx: *mut ffi::Context) -> Secp256k1> { + Secp256k1 { + ctx: raw_ctx, + phantom: PhantomData, + buf: ptr::null_mut::<[u8;0]>() as *mut [u8] , + } + } } impl<'buf> Secp256k1> { @@ -225,4 +264,23 @@ impl<'buf> Secp256k1> { pub fn preallocate_verification_size() -> usize { Self::preallocate_size_gen() } -} + + /// Create a context from a raw context. + /// + /// # Safety + /// This is highly unsafe, due to the number of conditions that aren't checked. + /// * `raw_ctx` needs to be a valid Secp256k1 context pointer. + /// that was generated by *exactly* the same code/version of the libsecp256k1 used here. + /// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1 + /// when generating the context. + /// * The user must handle the freeing of the context(using the correct functions) by himself. + /// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior., + /// + pub unsafe fn from_raw_verification_only(raw_ctx: *mut ffi::Context) -> Secp256k1> { + Secp256k1 { + ctx: raw_ctx, + phantom: PhantomData, + buf: ptr::null_mut::<[u8;0]>() as *mut [u8] , + } + } +} \ No newline at end of file From 9523e093c1c9a331fb120a101ef729a611a1ce55 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 6 Nov 2019 16:15:38 +0200 Subject: [PATCH 2/2] Add tests for raw context --- src/lib.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 854b166..584ddf9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -751,6 +751,41 @@ mod tests { unsafe { ffi::secp256k1_context_destroy(ctx_full) }; } + #[test] + fn test_raw_ctx() { + let ctx_full = Secp256k1::new(); + let ctx_sign = Secp256k1::signing_only(); + let ctx_vrfy = Secp256k1::verification_only(); + + let full = unsafe {Secp256k1::from_raw_all(ctx_full.ctx)}; + let sign = unsafe {Secp256k1::from_raw_signining_only(ctx_sign.ctx)}; + let vrfy = unsafe {Secp256k1::from_raw_verification_only(ctx_vrfy.ctx)}; + + let (sk, pk) = full.generate_keypair(&mut thread_rng()); + let msg = Message::from_slice(&[2u8; 32]).unwrap(); + // Try signing + assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk)); + let sig = full.sign(&msg, &sk); + + // Try verifying + assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); + assert!(full.verify(&msg, &sig, &pk).is_ok()); + + drop(full);drop(sign);drop(vrfy); + drop(ctx_full);drop(ctx_sign);drop(ctx_vrfy); + } + + #[test] + #[should_panic] + fn test_panic_raw_ctx() { + let ctx_vrfy = Secp256k1::verification_only(); + let raw_ctx_verify_as_full = unsafe {Secp256k1::from_raw_all(ctx_vrfy.ctx)}; + let (sk, _) = raw_ctx_verify_as_full.generate_keypair(&mut thread_rng()); + let msg = Message::from_slice(&[2u8; 32]).unwrap(); + // Try signing + raw_ctx_verify_as_full.sign(&msg, &sk); + } + #[test] fn test_preallocation() { let mut buf_ful = vec![0u8; Secp256k1::preallocate_size()];