Skip to content

Commit 758d74f

Browse files
authored
Merge pull request #9687 from holtrop-wolfssl/rust-hmac-blake2
Rust wrapper: add HMAC-BLAKE2[bs] wrappers
2 parents 418a3bf + 4a92ee3 commit 758d74f

File tree

5 files changed

+407
-5
lines changed

5 files changed

+407
-5
lines changed

wolfcrypt/src/blake2b.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,9 @@ int wc_Blake2bHmacInit(Blake2b* b2b, const byte* key, size_t key_len)
534534
ret = wc_Blake2bFinal(b2b, x_key, 0);
535535
} else {
536536
XMEMCPY(x_key, key, key_len);
537-
XMEMSET(x_key + key_len, 0, BLAKE2B_BLOCKBYTES - key_len);
537+
if (key_len < BLAKE2B_BLOCKBYTES) {
538+
XMEMSET(x_key + key_len, 0, BLAKE2B_BLOCKBYTES - key_len);
539+
}
538540
}
539541

540542
if (ret == 0) {
@@ -581,7 +583,9 @@ int wc_Blake2bHmacFinal(Blake2b* b2b, const byte* key, size_t key_len,
581583
ret = wc_Blake2bFinal(b2b, x_key, 0);
582584
} else {
583585
XMEMCPY(x_key, key, key_len);
584-
XMEMSET(x_key + key_len, 0, BLAKE2B_BLOCKBYTES - key_len);
586+
if (key_len < BLAKE2B_BLOCKBYTES) {
587+
XMEMSET(x_key + key_len, 0, BLAKE2B_BLOCKBYTES - key_len);
588+
}
585589
}
586590

587591
if (ret == 0) {

wolfcrypt/src/blake2s.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,9 @@ int wc_Blake2sHmacInit(Blake2s* b2s, const byte* key, size_t key_len)
528528
ret = wc_Blake2sFinal(b2s, x_key, 0);
529529
} else {
530530
XMEMCPY(x_key, key, key_len);
531-
XMEMSET(x_key + key_len, 0, BLAKE2S_BLOCKBYTES - key_len);
531+
if (key_len < BLAKE2S_BLOCKBYTES) {
532+
XMEMSET(x_key + key_len, 0, BLAKE2S_BLOCKBYTES - key_len);
533+
}
532534
}
533535

534536
if (ret == 0) {
@@ -575,7 +577,9 @@ int wc_Blake2sHmacFinal(Blake2s* b2s, const byte* key, size_t key_len,
575577
ret = wc_Blake2sFinal(b2s, x_key, 0);
576578
} else {
577579
XMEMCPY(x_key, key, key_len);
578-
XMEMSET(x_key + key_len, 0, BLAKE2S_BLOCKBYTES - key_len);
580+
if (key_len < BLAKE2S_BLOCKBYTES) {
581+
XMEMSET(x_key + key_len, 0, BLAKE2S_BLOCKBYTES - key_len);
582+
}
579583
}
580584

581585
if (ret == 0) {

wrapper/rust/wolfssl-wolfcrypt/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ fn scan_cfg() -> Result<()> {
128128

129129
/* blake2 */
130130
check_cfg(&binding, "wc_InitBlake2b", "blake2b");
131+
check_cfg(&binding, "wc_Blake2bHmac", "blake2b_hmac");
131132
check_cfg(&binding, "wc_InitBlake2s", "blake2s");
133+
check_cfg(&binding, "wc_Blake2sHmac", "blake2s_hmac");
132134

133135
/* chacha20_poly1305 */
134136
check_cfg(&binding, "wc_ChaCha20Poly1305_Encrypt", "chacha20_poly1305");

wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs

Lines changed: 276 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,144 @@ impl BLAKE2b {
167167
}
168168
}
169169

170+
171+
/// Context for HMAC-BLAKE2b computation.
172+
#[cfg(blake2b_hmac)]
173+
pub struct BLAKE2bHmac {
174+
wc_blake2b: sys::Blake2b,
175+
}
176+
177+
#[cfg(blake2b_hmac)]
178+
impl BLAKE2bHmac {
179+
/// HMAC-BLAKE2b digest size.
180+
pub const DIGEST_SIZE: usize = sys::WC_BLAKE2B_DIGEST_SIZE as usize;
181+
182+
/// Build a new BLAKE2bHmac instance.
183+
///
184+
/// # Parameters
185+
///
186+
/// * `key`: Key to use for HMAC-BLAKE2b computation.
187+
///
188+
/// # Returns
189+
///
190+
/// Returns either Ok(hmac_blake2b) or Err(e) containing the wolfSSL
191+
/// library error code value.
192+
///
193+
/// # Example
194+
///
195+
/// ```rust
196+
/// use wolfssl_wolfcrypt::blake2::BLAKE2bHmac;
197+
/// let key = [42u8, 43, 44];
198+
/// let hmac_blake2b = BLAKE2bHmac::new(&key).expect("Error with new()");
199+
/// ```
200+
pub fn new(key: &[u8]) -> Result<Self, i32> {
201+
let mut wc_blake2b: MaybeUninit<sys::Blake2b> = MaybeUninit::uninit();
202+
let rc = unsafe {
203+
sys::wc_Blake2bHmacInit(wc_blake2b.as_mut_ptr(), key.as_ptr(), key.len())
204+
};
205+
if rc != 0 {
206+
return Err(rc);
207+
}
208+
let wc_blake2b = unsafe { wc_blake2b.assume_init() };
209+
let hmac_blake2b = BLAKE2bHmac { wc_blake2b };
210+
Ok(hmac_blake2b)
211+
}
212+
213+
/// Update the HMAC-BLAKE2b computation with the input data.
214+
///
215+
/// This method may be called several times and then the finalize()
216+
/// method should be called to retrieve the final MAC.
217+
///
218+
/// # Parameters
219+
///
220+
/// * `data`: Input data to hash.
221+
///
222+
/// # Returns
223+
///
224+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
225+
/// library error code value.
226+
///
227+
/// # Example
228+
///
229+
/// ```rust
230+
/// use wolfssl_wolfcrypt::blake2::BLAKE2bHmac;
231+
/// let key = [42u8, 43, 44];
232+
/// let mut hmac_blake2b = BLAKE2bHmac::new(&key).expect("Error with new()");
233+
/// let data = [33u8, 34, 35];
234+
/// hmac_blake2b.update(&data).expect("Error with update()");
235+
/// ```
236+
pub fn update(&mut self, data: &[u8]) -> Result<(), i32> {
237+
let rc = unsafe {
238+
sys::wc_Blake2bHmacUpdate(&mut self.wc_blake2b, data.as_ptr(), data.len())
239+
};
240+
if rc != 0 {
241+
return Err(rc);
242+
}
243+
Ok(())
244+
}
245+
246+
/// Compute and retrieve the final HMAC-BLAKE2b MAC.
247+
///
248+
/// # Parameters
249+
///
250+
/// * `key`: Key to use for HMAC-BLAKE2b computation.
251+
/// * `mac`: Output buffer in which to store the computed HMAC-BLAKE2b MAC.
252+
/// It must be 64 bytes long.
253+
///
254+
/// # Returns
255+
///
256+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
257+
/// library error code value.
258+
///
259+
/// # Example
260+
///
261+
/// ```rust
262+
/// use wolfssl_wolfcrypt::blake2::BLAKE2bHmac;
263+
/// let key = [42u8, 43, 44];
264+
/// let mut hmac_blake2b = BLAKE2bHmac::new(&key).expect("Error with new()");
265+
/// let data = [33u8, 34, 35];
266+
/// hmac_blake2b.update(&data).expect("Error with update()");
267+
/// let mut mac = [0u8; 64];
268+
/// hmac_blake2b.finalize(&key, &mut mac).expect("Error with finalize()");
269+
/// ```
270+
pub fn finalize(&mut self, key: &[u8], mac: &mut [u8; Self::DIGEST_SIZE]) -> Result<(), i32> {
271+
let rc = unsafe {
272+
sys::wc_Blake2bHmacFinal(&mut self.wc_blake2b,
273+
key.as_ptr(), key.len(), mac.as_mut_ptr(), mac.len())
274+
};
275+
if rc != 0 {
276+
return Err(rc);
277+
}
278+
Ok(())
279+
}
280+
281+
/// Compute the HMAC-BLAKE2b message authentication code of the given
282+
/// input data using the given key (one-shot API).
283+
///
284+
/// # Parameters
285+
///
286+
/// * `data`: Input data to create MAC from.
287+
/// * `key`: Key to use for MAC creation.
288+
/// * `out`: Buffer in which to store the computed MAC. It must be 64 bytes
289+
/// long.
290+
///
291+
/// # Returns
292+
///
293+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
294+
/// library error code value.
295+
pub fn hmac(data: &[u8], key: &[u8], out: &mut [u8; Self::DIGEST_SIZE]) -> Result<(), i32> {
296+
let rc = unsafe {
297+
sys::wc_Blake2bHmac(data.as_ptr(), data.len(), key.as_ptr(),
298+
key.len(), out.as_mut_ptr(), out.len())
299+
};
300+
if rc != 0 {
301+
return Err(rc);
302+
}
303+
Ok(())
304+
}
305+
}
306+
307+
170308
/// Context for BLAKE2s computation.
171309
#[cfg(blake2s)]
172310
pub struct BLAKE2s {
@@ -291,7 +429,7 @@ impl BLAKE2s {
291429
/// use wolfssl_wolfcrypt::blake2::BLAKE2s;
292430
/// let mut blake2s = BLAKE2s::new(32).expect("Error with new()");
293431
/// blake2s.update(&[0u8; 16]).expect("Error with update()");
294-
/// let mut hash = [0u8; 64];
432+
/// let mut hash = [0u8; 32];
295433
/// blake2s.finalize(&mut hash).expect("Error with finalize()");
296434
/// ```
297435
pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> {
@@ -305,3 +443,140 @@ impl BLAKE2s {
305443
Ok(())
306444
}
307445
}
446+
447+
448+
/// Context for HMAC-BLAKE2s computation.
449+
#[cfg(blake2s_hmac)]
450+
pub struct BLAKE2sHmac {
451+
wc_blake2s: sys::Blake2s,
452+
}
453+
454+
#[cfg(blake2s_hmac)]
455+
impl BLAKE2sHmac {
456+
/// HMAC-BLAKE2s digest size.
457+
pub const DIGEST_SIZE: usize = sys::WC_BLAKE2S_DIGEST_SIZE as usize;
458+
459+
/// Build a new BLAKE2sHmac instance.
460+
///
461+
/// # Parameters
462+
///
463+
/// * `key`: Key to use for HMAC-BLAKE2s computation.
464+
///
465+
/// # Returns
466+
///
467+
/// Returns either Ok(hmac_blake2s) or Err(e) containing the wolfSSL
468+
/// library error code value.
469+
///
470+
/// # Example
471+
///
472+
/// ```rust
473+
/// use wolfssl_wolfcrypt::blake2::BLAKE2sHmac;
474+
/// let key = [42u8, 43, 44];
475+
/// let hmac_blake2s = BLAKE2sHmac::new(&key).expect("Error with new()");
476+
/// ```
477+
pub fn new(key: &[u8]) -> Result<Self, i32> {
478+
let mut wc_blake2s: MaybeUninit<sys::Blake2s> = MaybeUninit::uninit();
479+
let rc = unsafe {
480+
sys::wc_Blake2sHmacInit(wc_blake2s.as_mut_ptr(), key.as_ptr(), key.len())
481+
};
482+
if rc != 0 {
483+
return Err(rc);
484+
}
485+
let wc_blake2s = unsafe { wc_blake2s.assume_init() };
486+
let hmac_blake2s = BLAKE2sHmac { wc_blake2s };
487+
Ok(hmac_blake2s)
488+
}
489+
490+
/// Update the HMAC-BLAKE2s computation with the input data.
491+
///
492+
/// This method may be called several times and then the finalize()
493+
/// method should be called to retrieve the final MAC.
494+
///
495+
/// # Parameters
496+
///
497+
/// * `data`: Input data to hash.
498+
///
499+
/// # Returns
500+
///
501+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
502+
/// library error code value.
503+
///
504+
/// # Example
505+
///
506+
/// ```rust
507+
/// use wolfssl_wolfcrypt::blake2::BLAKE2sHmac;
508+
/// let key = [42u8, 43, 44];
509+
/// let mut hmac_blake2s = BLAKE2sHmac::new(&key).expect("Error with new()");
510+
/// let data = [33u8, 34, 35];
511+
/// hmac_blake2s.update(&data).expect("Error with update()");
512+
/// ```
513+
pub fn update(&mut self, data: &[u8]) -> Result<(), i32> {
514+
let rc = unsafe {
515+
sys::wc_Blake2sHmacUpdate(&mut self.wc_blake2s, data.as_ptr(), data.len())
516+
};
517+
if rc != 0 {
518+
return Err(rc);
519+
}
520+
Ok(())
521+
}
522+
523+
/// Compute and retrieve the final HMAC-BLAKE2s MAC.
524+
///
525+
/// # Parameters
526+
///
527+
/// * `key`: Key to use for HMAC-BLAKE2s computation.
528+
/// * `mac`: Output buffer in which to store the computed HMAC-BLAKE2s MAC.
529+
/// It must be 32 bytes long.
530+
///
531+
/// # Returns
532+
///
533+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
534+
/// library error code value.
535+
///
536+
/// # Example
537+
///
538+
/// ```rust
539+
/// use wolfssl_wolfcrypt::blake2::BLAKE2sHmac;
540+
/// let key = [42u8, 43, 44];
541+
/// let mut hmac_blake2s = BLAKE2sHmac::new(&key).expect("Error with new()");
542+
/// let data = [33u8, 34, 35];
543+
/// hmac_blake2s.update(&data).expect("Error with update()");
544+
/// let mut mac = [0u8; 32];
545+
/// hmac_blake2s.finalize(&key, &mut mac).expect("Error with finalize()");
546+
/// ```
547+
pub fn finalize(&mut self, key: &[u8], mac: &mut [u8; Self::DIGEST_SIZE]) -> Result<(), i32> {
548+
let rc = unsafe {
549+
sys::wc_Blake2sHmacFinal(&mut self.wc_blake2s,
550+
key.as_ptr(), key.len(), mac.as_mut_ptr(), mac.len())
551+
};
552+
if rc != 0 {
553+
return Err(rc);
554+
}
555+
Ok(())
556+
}
557+
558+
/// Compute the HMAC-BLAKE2s message authentication code of the given
559+
/// input data using the given key (one-shot API).
560+
///
561+
/// # Parameters
562+
///
563+
/// * `data`: Input data to create MAC from.
564+
/// * `key`: Key to use for MAC creation.
565+
/// * `out`: Buffer in which to store the computed MAC. It must be 32 bytes
566+
/// long.
567+
///
568+
/// # Returns
569+
///
570+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
571+
/// library error code value.
572+
pub fn hmac(data: &[u8], key: &[u8], out: &mut [u8; Self::DIGEST_SIZE]) -> Result<(), i32> {
573+
let rc = unsafe {
574+
sys::wc_Blake2sHmac(data.as_ptr(), data.len(), key.as_ptr(),
575+
key.len(), out.as_mut_ptr(), out.len())
576+
};
577+
if rc != 0 {
578+
return Err(rc);
579+
}
580+
Ok(())
581+
}
582+
}

0 commit comments

Comments
 (0)