From 3d847fbd6f70fb4811ba4f1a5faefa83c40e1586 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 30 Nov 2022 23:29:48 +0000 Subject: [PATCH] fix soundness issue with `preallocated_gen_new` Stop this from being a generic function over all contexts, to only a function generic over contexts where we can bound the lifetime precisely. Fixes #543 --- src/context.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/context.rs b/src/context.rs index d90d33290..ed91b3870 100644 --- a/src/context.rs +++ b/src/context.rs @@ -318,9 +318,9 @@ unsafe impl<'buf> Context for AllPreallocated<'buf> { } } -impl<'buf, C: Context + 'buf> Secp256k1 { +impl<'buf> PreallocatedContext<'buf> for Secp256k1> { /// Lets you create a context with a preallocated buffer in a generic manner (sign/verify/all). - pub fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result, Error> { + fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result { #[cfg(target_arch = "wasm32")] ffi::types::sanity_checks_for_wasm(); @@ -331,13 +331,58 @@ impl<'buf, C: Context + 'buf> Secp256k1 { ctx: unsafe { NonNull::new_unchecked(ffi::secp256k1_context_preallocated_create( buf.as_mut_c_ptr() as *mut c_void, - C::FLAGS, + AllPreallocated::FLAGS, )) }, phantom: PhantomData, }) } } +impl<'buf> PreallocatedContext<'buf> for Secp256k1> { + /// Lets you create a context with a preallocated buffer in a generic manner (sign/verify/all). + fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result { + #[cfg(target_arch = "wasm32")] + ffi::types::sanity_checks_for_wasm(); + + if buf.len() < Self::preallocate_size_gen() { + return Err(Error::NotEnoughMemory); + } + Ok(Secp256k1 { + ctx: unsafe { + NonNull::new_unchecked(ffi::secp256k1_context_preallocated_create( + buf.as_mut_c_ptr() as *mut c_void, + VerifyOnlyPreallocated::FLAGS, + )) + }, + phantom: PhantomData, + }) + } +} +impl<'buf> PreallocatedContext<'buf> for Secp256k1> { + /// Lets you create a context with a preallocated buffer in a generic manner (sign/verify/all). + fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result { + #[cfg(target_arch = "wasm32")] + ffi::types::sanity_checks_for_wasm(); + + if buf.len() < Self::preallocate_size_gen() { + return Err(Error::NotEnoughMemory); + } + Ok(Secp256k1 { + ctx: unsafe { + NonNull::new_unchecked(ffi::secp256k1_context_preallocated_create( + buf.as_mut_c_ptr() as *mut c_void, + SignOnlyPreallocated::FLAGS, + )) + }, + phantom: PhantomData, + }) + } +} + +trait PreallocatedContext<'buf>: Sized { + /// Lets you create a context with a preallocated buffer in a generic manner (sign/verify/all). + fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result; +} impl<'buf> Secp256k1> { /// Creates a new Secp256k1 context with all capabilities.