184 lines
6.4 KiB
Diff
184 lines
6.4 KiB
Diff
|
|
From 1ff6b4d427e85f290b68e3b9f547ca536360f32b Mon Sep 17 00:00:00 2001
|
||
|
|
From: Maurice Lam <yukl@google.com>
|
||
|
|
Date: Thu, 2 Feb 2023 19:45:12 +0000
|
||
|
|
Subject: [PATCH 3/3] Add HmacCtx wrapper for BoringSSL
|
||
|
|
|
||
|
|
---
|
||
|
|
openssl-sys/src/handwritten/hmac.rs | 2 +-
|
||
|
|
openssl/src/hmac.rs | 111 ++++++++++++++++++++++++----
|
||
|
|
2 files changed, 96 insertions(+), 17 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/openssl-sys/src/handwritten/hmac.rs b/openssl-sys/src/handwritten/hmac.rs
|
||
|
|
index 7cbb7cc9..7c0e0b5a 100644
|
||
|
|
--- a/openssl-sys/src/handwritten/hmac.rs
|
||
|
|
+++ b/openssl-sys/src/handwritten/hmac.rs
|
||
|
|
@@ -3,7 +3,7 @@ use libc::*;
|
||
|
|
use *;
|
||
|
|
|
||
|
|
cfg_if! {
|
||
|
|
- if #[cfg(any(ossl110, libressl350))] {
|
||
|
|
+ if #[cfg(any(ossl110, libressl350, boringssl))] {
|
||
|
|
extern "C" {
|
||
|
|
pub fn HMAC_CTX_new() -> *mut HMAC_CTX;
|
||
|
|
pub fn HMAC_CTX_free(ctx: *mut HMAC_CTX);
|
||
|
|
diff --git a/openssl/src/hmac.rs b/openssl/src/hmac.rs
|
||
|
|
index 601ae01b..90fd2175 100644
|
||
|
|
--- a/openssl/src/hmac.rs
|
||
|
|
+++ b/openssl/src/hmac.rs
|
||
|
|
@@ -1,10 +1,12 @@
|
||
|
|
-use crate::cvt_p;
|
||
|
|
+use crate::{cvt, cvt_p};
|
||
|
|
use crate::error::ErrorStack;
|
||
|
|
use crate::md::MdRef;
|
||
|
|
+use ffi::HMAC_CTX;
|
||
|
|
use foreign_types::ForeignTypeRef;
|
||
|
|
+use libc::{c_uint, c_void};
|
||
|
|
use openssl_macros::corresponds;
|
||
|
|
-use libc::{c_void, c_uint};
|
||
|
|
use std::convert::TryFrom;
|
||
|
|
+use std::ptr;
|
||
|
|
|
||
|
|
/// Computes the HMAC as a one-shot operation.
|
||
|
|
///
|
||
|
|
@@ -20,7 +22,7 @@ pub fn hmac<'a>(
|
||
|
|
md: &MdRef,
|
||
|
|
key: &[u8],
|
||
|
|
data: &[u8],
|
||
|
|
- out: &'a mut [u8]
|
||
|
|
+ out: &'a mut [u8],
|
||
|
|
) -> Result<&'a [u8], ErrorStack> {
|
||
|
|
let mut out_len = c_uint::try_from(out.len()).unwrap();
|
||
|
|
unsafe {
|
||
|
|
@@ -31,38 +33,115 @@ pub fn hmac<'a>(
|
||
|
|
data.as_ptr(),
|
||
|
|
data.len(),
|
||
|
|
out.as_mut_ptr(),
|
||
|
|
- &mut out_len
|
||
|
|
- ))?;
|
||
|
|
+ &mut out_len,
|
||
|
|
+ ))?;
|
||
|
|
}
|
||
|
|
Ok(&out[..out_len as usize])
|
||
|
|
}
|
||
|
|
|
||
|
|
+/// Only available in boringssl. For openssl, use `PKey::hmac` instead.
|
||
|
|
+#[cfg(boringssl)]
|
||
|
|
+pub struct HmacCtx {
|
||
|
|
+ ctx: *mut HMAC_CTX,
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+#[cfg(boringssl)]
|
||
|
|
+impl HmacCtx {
|
||
|
|
+ #[corresponds(HMAC_CTX_new)]
|
||
|
|
+ pub fn new(key: &[u8], md: &MdRef) -> Result<Self, ErrorStack> {
|
||
|
|
+ unsafe {
|
||
|
|
+ let ctx = cvt_p(ffi::HMAC_CTX_new())?;
|
||
|
|
+ cvt(ffi::HMAC_Init_ex(
|
||
|
|
+ ctx,
|
||
|
|
+ key.as_ptr() as *const c_void,
|
||
|
|
+ key.len(),
|
||
|
|
+ md.as_ptr(),
|
||
|
|
+ ptr::null_mut(),
|
||
|
|
+ ))?;
|
||
|
|
+ Ok(Self { ctx })
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||
|
|
+ unsafe { cvt(ffi::HMAC_Update(self.ctx, data.as_ptr(), data.len())).map(|_| ()) }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ /// Finishes the HMAC process, writing any remaining data to `output`.
|
||
|
|
+ /// The number of bytes written to `output` is returned.
|
||
|
|
+ /// `update` should not be called after this method.
|
||
|
|
+ pub fn finalize(&mut self, md: &mut [u8]) -> Result<usize, ErrorStack> {
|
||
|
|
+ unsafe {
|
||
|
|
+ let mut size: c_uint = 0;
|
||
|
|
+ cvt(ffi::HMAC_Final(
|
||
|
|
+ self.ctx,
|
||
|
|
+ md.as_mut_ptr(),
|
||
|
|
+ &mut size as *mut c_uint,
|
||
|
|
+ ))
|
||
|
|
+ .map(|_| size as usize)
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+impl Drop for HmacCtx {
|
||
|
|
+ #[corresponds(HMAC_CTX_free)]
|
||
|
|
+ fn drop(&mut self) {
|
||
|
|
+ unsafe {
|
||
|
|
+ ffi::HMAC_CTX_free(self.ctx);
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
use crate::md::Md;
|
||
|
|
- use crate::memcmp;
|
||
|
|
|
||
|
|
- const SHA_256_DIGEST_SIZE:usize = 32;
|
||
|
|
+ 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 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 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));
|
||
|
|
+ let hmac_result =
|
||
|
|
+ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
|
||
|
|
+ assert_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 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 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");
|
||
|
|
+ assert_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
|
||
|
|
+ assert_eq!(&hmac_result, &expected_hmac);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ #[test]
|
||
|
|
+ fn hmac_sha256_update_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_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
|
||
|
|
- expect!(memcmp::eq(&hmac_result, &expected_hmac));
|
||
|
|
+ let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap();
|
||
|
|
+ hmac_ctx.update(data).unwrap();
|
||
|
|
+ hmac_ctx.finalize(&mut out).unwrap();
|
||
|
|
+ assert_eq!(&out, &expected_hmac);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
--
|
||
|
|
2.39.1.519.gcb327c4b5f-goog
|
||
|
|
|