Skip to content

Commit cca6642

Browse files
committed
Add AlignType and use it for buffer allocations
1 parent de21642 commit cca6642

File tree

3 files changed

+101
-37
lines changed

3 files changed

+101
-37
lines changed

src/context.rs

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@ use Secp256k1;
77
#[cfg(feature = "std")]
88
pub use self::std_only::*;
99

10+
11+
12+
/// A type that represents the type with the biggest alignment we can get in rust.
13+
/// Trying to match what `malloc` does in C, this should be aligned enough to contain pointers too.
14+
/// This type can have different size/alignment depending on the architecture.
15+
#[cfg(any(target_pointer_width = "32", target_pointer_width = "16", target_pointer_wid = "8"))]
16+
pub type AlignType = u64;
17+
18+
/// A type that represents the type with the biggest alignment we can get in rust.
19+
/// Trying to match what `malloc` does in C, this should be aligned enough to contain pointers too.
20+
/// This type can have different size/alignment depending on the architecture.
21+
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "16", target_pointer_wid = "8")))]
22+
pub type AlignType = usize;
23+
24+
1025
/// A trait for all kinds of Context's that Lets you define the exact flags and a function to deallocate memory.
1126
/// * DO NOT * implement it for your own types.
1227
pub unsafe trait Context {
@@ -15,7 +30,7 @@ pub unsafe trait Context {
1530
/// A constant description of the context.
1631
const DESCRIPTION: &'static str;
1732
/// A function to deallocate the memory when the context is dropped.
18-
fn deallocate(ptr: *mut [u8]);
33+
fn deallocate(ptr: *mut [AlignType]);
1934
}
2035

2136
/// Marker trait for indicating that an instance of `Secp256k1` can be used for signing.
@@ -62,7 +77,7 @@ mod std_only {
6277
const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
6378
const DESCRIPTION: &'static str = "signing only";
6479

65-
fn deallocate(ptr: *mut [u8]) {
80+
fn deallocate(ptr: *mut [AlignType]) {
6681
let _ = unsafe { Box::from_raw(ptr) };
6782
}
6883
}
@@ -71,7 +86,7 @@ mod std_only {
7186
const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
7287
const DESCRIPTION: &'static str = "verification only";
7388

74-
fn deallocate(ptr: *mut [u8]) {
89+
fn deallocate(ptr: *mut [AlignType]) {
7590
let _ = unsafe { Box::from_raw(ptr) };
7691
}
7792
}
@@ -80,15 +95,15 @@ mod std_only {
8095
const FLAGS: c_uint = VerifyOnly::FLAGS | SignOnly::FLAGS;
8196
const DESCRIPTION: &'static str = "all capabilities";
8297

83-
fn deallocate(ptr: *mut [u8]) {
98+
fn deallocate(ptr: *mut [AlignType]) {
8499
let _ = unsafe { Box::from_raw(ptr) };
85100
}
86101
}
87102

88103
impl<C: Context> Secp256k1<C> {
89104
/// Lets you create a context in a generic manner(sign/verify/all)
90105
pub fn gen_new() -> Secp256k1<C> {
91-
let buf = vec![0u8; Self::preallocate_size_gen()].into_boxed_slice();
106+
let buf = vec![0 as AlignType; Self::preallocate_size_gen()].into_boxed_slice();
92107
let ptr = Box::into_raw(buf);
93108
Secp256k1 {
94109
ctx: unsafe { ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS) },
@@ -128,7 +143,7 @@ mod std_only {
128143
impl<C: Context> Clone for Secp256k1<C> {
129144
fn clone(&self) -> Secp256k1<C> {
130145
let clone_size = unsafe {ffi::secp256k1_context_preallocated_clone_size(self.ctx)};
131-
let ptr_buf = Box::into_raw(vec![0u8; clone_size].into_boxed_slice());
146+
let ptr_buf = Box::into_raw(vec![0 as AlignType; clone_size].into_boxed_slice());
132147
Secp256k1 {
133148
ctx: unsafe { ffi::secp256k1_context_preallocated_clone(self.ctx, ptr_buf as *mut c_void) },
134149
phantom: PhantomData,
@@ -149,7 +164,7 @@ unsafe impl<'buf> Context for SignOnlyPreallocated<'buf> {
149164
const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
150165
const DESCRIPTION: &'static str = "signing only";
151166

152-
fn deallocate(_ptr: *mut [u8]) {
167+
fn deallocate(_ptr: *mut [AlignType]) {
153168
// Allocated by the user
154169
}
155170
}
@@ -158,7 +173,7 @@ unsafe impl<'buf> Context for VerifyOnlyPreallocated<'buf> {
158173
const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
159174
const DESCRIPTION: &'static str = "verification only";
160175

161-
fn deallocate(_ptr: *mut [u8]) {
176+
fn deallocate(_ptr: *mut [AlignType]) {
162177
// Allocated by the user
163178
}
164179
}
@@ -167,14 +182,14 @@ unsafe impl<'buf> Context for AllPreallocated<'buf> {
167182
const FLAGS: c_uint = SignOnlyPreallocated::FLAGS | VerifyOnlyPreallocated::FLAGS;
168183
const DESCRIPTION: &'static str = "all capabilities";
169184

170-
fn deallocate(_ptr: *mut [u8]) {
185+
fn deallocate(_ptr: *mut [AlignType]) {
171186
// Allocated by the user
172187
}
173188
}
174189

175190
impl<'buf, C: Context + 'buf> Secp256k1<C> {
176191
/// Lets you create a context with preallocated buffer in a generic manner(sign/verify/all)
177-
pub fn preallocated_gen_new(buf: &'buf mut [u8]) -> Result<Secp256k1<C>, Error> {
192+
pub fn preallocated_gen_new(buf: &'buf mut [AlignType]) -> Result<Secp256k1<C>, Error> {
178193
if buf.len() < Self::preallocate_size_gen() {
179194
return Err(Error::NotEnoughMemory);
180195
}
@@ -185,29 +200,51 @@ impl<'buf, C: Context + 'buf> Secp256k1<C> {
185200
C::FLAGS)
186201
},
187202
phantom: PhantomData,
188-
buf: buf as *mut [u8],
203+
buf: buf as *mut [AlignType],
189204
})
190205
}
191206
}
192207

193208
impl<'buf> Secp256k1<AllPreallocated<'buf>> {
194209
/// Creates a new Secp256k1 context with all capabilities
195-
pub fn preallocated_new(buf: &'buf mut [u8]) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
210+
pub fn preallocated_new(buf: &'buf mut [AlignType]) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
196211
Secp256k1::preallocated_gen_new(buf)
197212
}
198-
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context
213+
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all)
214+
///
215+
/// Notice that the memory returned is in [AlignedType](type.AlignType.html)
216+
///
217+
/// ## Examples
218+
/// ```rust
219+
/// # use secp256k1::*;
220+
/// let buf_size = Secp256k1::preallocate_size();
221+
/// let mut buf = vec![0; buf_size];
222+
/// let secp = Secp256k1::preallocated_new(&mut buf).unwrap();
223+
///
224+
/// ```
199225
pub fn preallocate_size() -> usize {
200226
Self::preallocate_size_gen()
201227
}
202228
}
203229

204230
impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
205231
/// Creates a new Secp256k1 context that can only be used for signing
206-
pub fn preallocated_signing_only(buf: &'buf mut [u8]) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
232+
pub fn preallocated_signing_only(buf: &'buf mut [AlignType]) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
207233
Secp256k1::preallocated_gen_new(buf)
208234
}
209235

210-
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context
236+
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all)
237+
///
238+
/// Notice that the memory returned is in [AlignedType](type.AlignType.html)
239+
///
240+
/// ## Examples
241+
/// ```rust
242+
/// # use secp256k1::*;
243+
/// let buf_size = Secp256k1::preallocate_signing_size();
244+
/// let mut buf = vec![0; buf_size];
245+
/// let secp = Secp256k1::preallocated_signing_only(&mut buf).unwrap();
246+
///
247+
/// ```
211248
#[inline]
212249
pub fn preallocate_signing_size() -> usize {
213250
Self::preallocate_size_gen()
@@ -216,11 +253,22 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
216253

217254
impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
218255
/// Creates a new Secp256k1 context that can only be used for verification
219-
pub fn preallocated_verification_only(buf: &'buf mut [u8]) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
256+
pub fn preallocated_verification_only(buf: &'buf mut [AlignType]) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
220257
Secp256k1::preallocated_gen_new(buf)
221258
}
222259

223-
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context
260+
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all)
261+
///
262+
/// Notice that the memory returned is in [AlignedType](type.AlignType.html)
263+
///
264+
/// ## Examples
265+
/// ```rust
266+
/// # use secp256k1::*;
267+
/// let buf_size = Secp256k1::preallocate_verification_size();
268+
/// let mut buf = vec![0; buf_size];
269+
/// let secp = Secp256k1::preallocated_verification_only(&mut buf).unwrap();
270+
///
271+
/// ```
224272
#[inline]
225273
pub fn preallocate_verification_size() -> usize {
226274
Self::preallocate_size_gen()

src/ffi.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
//! not be needed for most users.
1919
use core::{mem, hash, slice};
2020
use types::*;
21+
use context::AlignType;
2122

2223
/// Flag for context to enable no precomputation
2324
pub const SECP256K1_START_NONE: c_uint = 1;
@@ -271,16 +272,18 @@ extern "C" {
271272
// Returns: a newly created context object.
272273
// In: flags: which parts of the context to initialize.
273274
pub unsafe extern "C" fn secp256k1_context_create(flags: c_uint) -> *mut Context {
274-
assert!(mem::align_of::<usize>() >= mem::align_of::<u8>());
275-
assert_eq!(mem::size_of::<usize>(), mem::size_of::<&usize>());
275+
assert!(mem::align_of::<AlignType>() >= mem::align_of::<u8>());
276+
assert!(mem::align_of::<AlignType>() >= mem::align_of::<usize>());
277+
assert!(mem::size_of::<AlignType>() >= mem::size_of::<usize>());
278+
assert!(mem::align_of::<AlignType>() >= mem::align_of::<&AlignType>());
276279

277-
let word_size = mem::size_of::<usize>();
280+
let word_size = mem::size_of::<AlignType>();
278281
let n_words = (secp256k1_context_preallocated_size(flags) + word_size - 1) / word_size;
279282

280-
let buf = vec![0usize; n_words + 1].into_boxed_slice();
281-
let ptr = Box::into_raw(buf) as *mut usize;
282-
::core::ptr::write(ptr, n_words);
283-
let ptr: *mut usize = ptr.offset(1);
283+
let buf = vec![0 as AlignType; n_words + 1].into_boxed_slice();
284+
let ptr = Box::into_raw(buf) as *mut AlignType;
285+
::core::ptr::write(ptr, n_words as AlignType);
286+
let ptr: *mut AlignType = ptr.offset(1);
284287

285288
secp256k1_context_preallocated_create(ptr as *mut c_void, flags)
286289
}
@@ -295,12 +298,12 @@ pub unsafe extern "C" fn secp256k1_context_create(flags: c_uint) -> *mut Context
295298
///
296299
pub unsafe extern "C" fn secp256k1_context_destroy(ctx: *mut Context) {
297300
secp256k1_context_preallocated_destroy(ctx);
298-
let ctx: *mut usize = ctx as *mut usize;
301+
let ctx: *mut AlignType = ctx as *mut AlignType;
299302

300-
let n_words_ptr: *mut usize = ctx.offset(-1);
301-
let n_words: usize = ::core::ptr::read(n_words_ptr);
302-
let slice: &mut [usize] = slice::from_raw_parts_mut(n_words_ptr , n_words+1);
303-
let _ = Box::from_raw(slice as *mut [usize]);
303+
let n_words_ptr: *mut AlignType = ctx.offset(-1);
304+
let n_words: AlignType = ::core::ptr::read(n_words_ptr);
305+
let slice: &mut [AlignType] = slice::from_raw_parts_mut(n_words_ptr , (n_words+1) as usize);
306+
let _ = Box::from_raw(slice as *mut [AlignType]);
304307
}
305308

306309

src/lib.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@
143143
#[cfg(any(test, feature = "rand"))] use rand::Rng;
144144
#[cfg(any(test, feature = "std"))] extern crate core;
145145

146-
use core::{fmt, ptr, str};
146+
use core::{fmt, mem, ptr, str};
147+
148+
pub use context::AlignType;
147149

148150
#[macro_use]
149151
mod macros;
@@ -502,7 +504,7 @@ impl std::error::Error for Error {
502504
pub struct Secp256k1<C: Context> {
503505
ctx: *mut ffi::Context,
504506
phantom: PhantomData<C>,
505-
buf: *mut [u8],
507+
buf: *mut [AlignType],
506508
}
507509

508510
// The underlying secp context does not contain any references to memory it does not own
@@ -571,8 +573,19 @@ impl<C: Context> Secp256k1<C> {
571573
}
572574

573575
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all)
576+
///
577+
/// Notice that the memory returned is in [AlignedType](type.AlignType.html)
578+
///
574579
pub fn preallocate_size_gen() -> usize {
575-
unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) }
580+
assert!(mem::align_of::<AlignType>() >= mem::align_of::<u8>());
581+
assert!(mem::align_of::<AlignType>() >= mem::align_of::<usize>());
582+
assert!(mem::size_of::<AlignType>() >= mem::size_of::<usize>());
583+
assert!(mem::align_of::<AlignType>() >= mem::align_of::<&AlignType>());
584+
585+
let bytes_size = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) };
586+
let word_size = mem::size_of::<AlignType>();
587+
let n_words = (bytes_size + word_size - 1) / word_size;
588+
n_words
576589
}
577590

578591
/// (Re)randomizes the Secp256k1 context for cheap sidechannel resistance;
@@ -706,7 +719,7 @@ mod tests {
706719
let ctx_sign = unsafe { ffi::secp256k1_context_create(SignOnlyPreallocated::FLAGS) };
707720
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
708721

709-
let buf: *mut [u8] = &mut [0u8;0] as _;
722+
let buf: *mut [AlignType] = &mut [0 as AlignType;0] as _;
710723
let full: Secp256k1<AllPreallocated> = Secp256k1{ctx: ctx_full, phantom: PhantomData, buf};
711724
let sign: Secp256k1<SignOnlyPreallocated> = Secp256k1{ctx: ctx_sign, phantom: PhantomData, buf};
712725
let vrfy: Secp256k1<VerifyOnlyPreallocated> = Secp256k1{ctx: ctx_vrfy, phantom: PhantomData, buf};
@@ -730,10 +743,10 @@ mod tests {
730743

731744
#[test]
732745
fn test_preallocation() {
733-
let mut buf_ful = vec![0u8; Secp256k1::preallocate_size()];
734-
let mut buf_sign = vec![0u8; Secp256k1::preallocate_signing_size()];
735-
let mut buf_vfy = vec![0u8; Secp256k1::preallocate_verification_size()];
736-
//
746+
let mut buf_ful = vec![0; Secp256k1::preallocate_size()];
747+
let mut buf_sign = vec![0; Secp256k1::preallocate_signing_size()];
748+
let mut buf_vfy = vec![0; Secp256k1::preallocate_verification_size()];
749+
737750
let full = Secp256k1::preallocated_new(&mut buf_ful).unwrap();
738751
let sign = Secp256k1::preallocated_signing_only(&mut buf_sign).unwrap();
739752
let vrfy = Secp256k1::preallocated_verification_only(&mut buf_vfy).unwrap();

0 commit comments

Comments
 (0)