Splitting the sign::Signer::finish function, to avoid allocations

This commit is contained in:
pe@pijul.org 2017-12-03 12:10:21 +01:00
parent 490e8a4f69
commit 905d3f716b
1 changed files with 28 additions and 5 deletions

View File

@ -139,7 +139,8 @@ impl<'a> Signer<'a> {
} }
} }
pub fn finish(&self) -> Result<Vec<u8>, ErrorStack> { /// Computes an upper bound on the signature length.
pub fn finish_len(&self) -> Result<usize, ErrorStack> {
unsafe { unsafe {
let mut len = 0; let mut len = 0;
cvt(ffi::EVP_DigestSignFinal( cvt(ffi::EVP_DigestSignFinal(
@ -147,17 +148,39 @@ impl<'a> Signer<'a> {
ptr::null_mut(), ptr::null_mut(),
&mut len, &mut len,
))?; ))?;
let mut buf = vec![0; len]; Ok(len)
}
}
/// Outputs the signature into the provided buffer, returning the
/// length of that buffer.
///
/// This method will fail if the buffer is not large enough for
/// the signature, one can use `finish_len` to get an upper bound
/// on the required size.
pub fn finish_into<B:AsMut<[u8]>>(&self, mut buf: B) -> Result<usize, ErrorStack> {
unsafe {
let buf = buf.as_mut();
let mut len = buf.len();
cvt(ffi::EVP_DigestSignFinal( cvt(ffi::EVP_DigestSignFinal(
self.md_ctx, self.md_ctx,
buf.as_mut_ptr() as *mut _, buf.as_mut_ptr() as *mut _,
&mut len, &mut len,
))?; ))?;
// The advertised length is not always equal to the real length for things like DSA Ok(len)
buf.truncate(len);
Ok(buf)
} }
} }
/// Combines `self.finish_len()` and `self.finish_into()`,
/// allocating a vector of the correct size for the signature.
pub fn finish(&self) -> Result<Vec<u8>, ErrorStack> {
let mut buf = vec![0; self.finish_len()?];
let len = self.finish_into(&mut buf)?;
// The advertised length is not always equal to the real
// length for things like DSA
buf.truncate(len);
Ok(buf)
}
} }
impl<'a> Write for Signer<'a> { impl<'a> Write for Signer<'a> {