From 2f73d3148a85397c6022c27471d5f8a148a0c603 Mon Sep 17 00:00:00 2001 From: sabjank Date: Fri, 17 Feb 2023 18:04:30 +0100 Subject: [PATCH] Expose SHA512-256 --- boring/src/hash.rs | 4 +++ boring/src/nid.rs | 1 + boring/src/sha.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/boring/src/hash.rs b/boring/src/hash.rs index 011fa54b..8565e82b 100644 --- a/boring/src/hash.rs +++ b/boring/src/hash.rs @@ -64,6 +64,10 @@ impl MessageDigest { unsafe { MessageDigest(ffi::EVP_sha512()) } } + pub fn sha512_256() -> MessageDigest { + unsafe { MessageDigest(ffi::EVP_sha512_256()) } + } + #[allow(clippy::trivially_copy_pass_by_ref)] pub fn as_ptr(&self) -> *const ffi::EVP_MD { self.0 diff --git a/boring/src/nid.rs b/boring/src/nid.rs index 52b0c2d6..8f9b400a 100644 --- a/boring/src/nid.rs +++ b/boring/src/nid.rs @@ -728,6 +728,7 @@ impl Nid { pub const SHA256: Nid = Nid(ffi::NID_sha256); pub const SHA384: Nid = Nid(ffi::NID_sha384); pub const SHA512: Nid = Nid(ffi::NID_sha512); + pub const SHA512_256: Nid = Nid(ffi::NID_sha512_256); pub const SHA224: Nid = Nid(ffi::NID_sha224); pub const DSA_WITH_SHA224: Nid = Nid(ffi::NID_dsa_with_SHA224); pub const DSA_WITH_SHA256: Nid = Nid(ffi::NID_dsa_with_SHA256); diff --git a/boring/src/sha.rs b/boring/src/sha.rs index 66fd8ad2..98aa26ba 100644 --- a/boring/src/sha.rs +++ b/boring/src/sha.rs @@ -107,6 +107,17 @@ pub fn sha512(data: &[u8]) -> [u8; 64] { } } +/// Computes the SHA512-256 hash of some data. +#[inline] +#[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566 +pub fn sha512_256(data: &[u8]) -> [u8; 32] { + unsafe { + let mut hash: MaybeUninit<[u8; 32]> = MaybeUninit::uninit(); + ffi::SHA512_256(data.as_ptr(), data.len(), hash.as_mut_ptr().cast()); + hash.assume_init() + } +} + /// An object which calculates a SHA1 hash of some data. /// /// # Warning @@ -337,6 +348,51 @@ impl Sha512 { } } +/// An object which calculates a SHA512-256 hash of some data. +#[derive(Clone)] +pub struct Sha512_256(ffi::SHA512_CTX); + +impl Default for Sha512_256 { + #[inline] + fn default() -> Sha512_256 { + Sha512_256::new() + } +} + +impl Sha512_256 { + /// Creates a new hasher. + #[inline] + #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566 + pub fn new() -> Sha512_256 { + unsafe { + let mut ctx = MaybeUninit::uninit(); + ffi::SHA512_256_Init(ctx.as_mut_ptr()); + Sha512_256(ctx.assume_init()) + } + } + + /// Feeds some data into the hasher. + /// + /// This can be called multiple times. + #[inline] + pub fn update(&mut self, buf: &[u8]) { + unsafe { + ffi::SHA512_256_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); + } + } + + /// Returns the hash of the data. + #[inline] + #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566 + pub fn finish(mut self) -> [u8; 32] { + unsafe { + let mut hash: MaybeUninit<[u8; 32]> = MaybeUninit::uninit(); + ffi::SHA512_256_Final(hash.as_mut_ptr().cast(), &mut self.0); + hash.assume_init() + } + } +} + #[cfg(test)] mod test { use hex; @@ -454,4 +510,22 @@ mod test { hasher.update(b"bc"); assert_eq!(hex::encode(&hasher.finish()[..]), expected); } + + #[test] + fn standalone_512_256() { + let data = b"abc"; + let expected = "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"; + + assert_eq!(hex::encode(&sha512_256(data)[..]), expected); + } + + #[test] + fn struct_512_256() { + let expected = "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"; + + let mut hasher = Sha512_256::new(); + hasher.update(b"a"); + hasher.update(b"bc"); + assert_eq!(hex::encode(&hasher.finish()[..]), expected); + } }