75 lines
2.6 KiB
Diff
75 lines
2.6 KiB
Diff
diff --git a/src/hmac.rs b/src/hmac.rs
|
|
new file mode 100644
|
|
index 0000000..601ae01
|
|
--- /dev/null
|
|
+++ b/src/hmac.rs
|
|
@@ -0,0 +1,68 @@
|
|
+use crate::cvt_p;
|
|
+use crate::error::ErrorStack;
|
|
+use crate::md::MdRef;
|
|
+use foreign_types::ForeignTypeRef;
|
|
+use openssl_macros::corresponds;
|
|
+use libc::{c_void, c_uint};
|
|
+use std::convert::TryFrom;
|
|
+
|
|
+/// Computes the HMAC as a one-shot operation.
|
|
+///
|
|
+/// Calculates the HMAC of data, using the given |key|
|
|
+/// and hash function |md|, and returns the result re-using the space from
|
|
+/// buffer |out|. On entry, |out| must contain at least |EVP_MD_size| bytes
|
|
+/// of space. The actual length of the result is used to resize the returned
|
|
+/// slice. An output size of |EVP_MAX_MD_SIZE| will always be large enough.
|
|
+/// It returns a resized |out| or ErrorStack on error.
|
|
+#[corresponds(HMAC)]
|
|
+#[inline]
|
|
+pub fn hmac<'a>(
|
|
+ md: &MdRef,
|
|
+ key: &[u8],
|
|
+ data: &[u8],
|
|
+ out: &'a mut [u8]
|
|
+) -> Result<&'a [u8], ErrorStack> {
|
|
+ let mut out_len = c_uint::try_from(out.len()).unwrap();
|
|
+ unsafe {
|
|
+ cvt_p(ffi::HMAC(
|
|
+ md.as_ptr(),
|
|
+ key.as_ptr() as *const c_void,
|
|
+ key.len(),
|
|
+ data.as_ptr(),
|
|
+ data.len(),
|
|
+ out.as_mut_ptr(),
|
|
+ &mut out_len
|
|
+ ))?;
|
|
+ }
|
|
+ Ok(&out[..out_len as usize])
|
|
+}
|
|
+
|
|
+#[cfg(test)]
|
|
+mod tests {
|
|
+ use super::*;
|
|
+ use crate::md::Md;
|
|
+ use crate::memcmp;
|
|
+
|
|
+ const SHA_256_DIGEST_SIZE:usize = 32;
|
|
+
|
|
+ #[test]
|
|
+ fn hmac_sha256_test() {
|
|
+ let expected_hmac = [0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7];
|
|
+ let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
|
|
+ let key:[u8; 20] = [0x0b; 20];
|
|
+ let data = b"Hi There";
|
|
+ let hmac_result = hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
|
|
+ expect!(memcmp::eq(&hmac_result, &expected_hmac));
|
|
+ }
|
|
+
|
|
+ #[test]
|
|
+ fn hmac_sha256_test_big_buffer() {
|
|
+ let expected_hmac = [0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7];
|
|
+ let mut out: [u8; 100] = [0; 100];
|
|
+ let key:[u8;20] = [0x0b; 20];
|
|
+ let data = b"Hi There";
|
|
+ let hmac_result = hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
|
|
+ expect_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
|
|
+ expect!(memcmp::eq(&hmac_result, &expected_hmac));
|
|
+ }
|
|
+}
|