1use crate::error::ErrorStack;
2use crate::md::MdRef;
3use crate::util::ForeignTypeRefExt;
4use crate::{cvt, cvt_p};
5use foreign_types::{ForeignType, ForeignTypeRef};
6use openssl_macros::corresponds;
7use std::ptr;
8
9foreign_type_and_impl_send_sync! {
10 type CType = ffi::HMAC_CTX;
11 fn drop = ffi::HMAC_CTX_free;
12
13 pub struct HMacCtx;
15 pub struct HMacCtxRef;
17}
18
19impl HMacCtx {
20 #[corresponds(HMAC_CTX_new)]
22 pub fn new() -> Result<Self, ErrorStack> {
23 ffi::init();
24
25 unsafe {
26 let ptr = cvt_p(ffi::HMAC_CTX_new())?;
27 Ok(HMacCtx::from_ptr(ptr))
28 }
29 }
30}
31
32impl HMacCtxRef {
33 #[corresponds(HMAC_CTX_reset)]
37 #[cfg(any(ossl110, libressl350))]
38 #[inline]
39 pub fn reset(&mut self) -> Result<(), ErrorStack> {
40 unsafe {
41 let _ = cvt(ffi::HMAC_CTX_reset(self.as_ptr()))?;
42 Ok(())
43 }
44 }
45
46 #[corresponds(HMAC_CTX_reset)]
50 #[cfg(any(boringssl, awslc))]
51 #[inline]
52 pub fn reset(&mut self) -> Result<(), ErrorStack> {
53 unsafe {
54 ffi::HMAC_CTX_reset(self.as_ptr());
55 Ok(())
56 }
57 }
58
59 #[corresponds(HMAC_CTX_copy)]
60 pub fn copy(&mut self, src: &HMacCtxRef) -> Result<(), ErrorStack> {
61 unsafe {
62 cvt(ffi::HMAC_CTX_copy(self.as_ptr(), src.as_ptr()))?;
63 Ok(())
64 }
65 }
66
67 #[corresponds(HMAC_Init_ex)]
68 pub fn init_ex(&mut self, key: Option<&[u8]>, md: &MdRef) -> Result<(), ErrorStack> {
69 let key_len = key.map(|v| v.len()).unwrap_or_default();
70 #[cfg(not(any(boringssl, awslc)))]
71 let key_len = i32::try_from(key_len).unwrap();
72 let key = key.map(|v| v.as_ptr()).unwrap_or(ptr::null());
73 unsafe {
74 cvt(ffi::HMAC_Init_ex(
75 self.as_ptr(),
76 key as _,
77 key_len,
78 md.as_ptr(),
79 ptr::null_mut(),
80 ))?;
81 Ok(())
82 }
83 }
84
85 #[corresponds(HMAC_CTX_get_md)]
86 pub fn md(&self) -> Option<&MdRef> {
87 unsafe {
88 let ptr = ffi::HMAC_CTX_get_md(self.as_ptr());
89 if ptr.is_null() {
90 None
91 } else {
92 Some(MdRef::from_const_ptr(ptr))
93 }
94 }
95 }
96
97 #[corresponds(HMAC_size)]
101 #[cfg(any(ossl110, boringssl, awslc))]
102 pub fn size(&self) -> usize {
103 unsafe { ffi::HMAC_size(self.as_ptr()) }
105 }
106
107 #[cfg(not(any(ossl110, boringssl, awslc)))]
111 pub fn size(&self) -> usize {
112 self.md().map(|md| md.size()).unwrap_or_default()
113 }
114
115 #[corresponds(HMAC_Update)]
117 #[inline]
118 pub fn hmac_update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
119 unsafe {
120 cvt(ffi::HMAC_Update(
121 self.as_ptr(),
122 data.as_ptr() as *const _,
123 data.len(),
124 ))?;
125 }
126
127 Ok(())
128 }
129
130 #[corresponds(HMAC_Update)]
132 pub fn hmac_final(&mut self, out: &mut [u8]) -> Result<usize, ErrorStack> {
133 let mut len = u32::try_from(out.len()).unwrap_or(u32::MAX);
134
135 unsafe {
136 cvt(ffi::HMAC_Final(self.as_ptr(), out.as_mut_ptr(), &mut len))?;
137 }
138
139 Ok(len as usize)
140 }
141
142 pub fn hmac_final_to_vec(&mut self, out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
144 let base = out.len();
145 out.resize(base + self.size(), 0);
146 let len = self.hmac_final(&mut out[base..])?;
147 out.truncate(base + len);
148 Ok(len)
149 }
150}