Harden key material zeroization paths
Reduce secret lifetime in HKDF and HMAC internals, avoid extra shared-secret copying in key exchange, and add SHA384 HMAC coverage to guard output sizing.
This commit is contained in:
parent
c71d5bbfd8
commit
bbd0ccf0b8
3 changed files with 32 additions and 12 deletions
|
|
@ -2,6 +2,7 @@ use std::marker::PhantomData;
|
|||
|
||||
use boring::hash::MessageDigest;
|
||||
use rustls::crypto::tls13::{self, Hkdf as RustlsHkdf};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use crate::helper::{cvt, cvt_p};
|
||||
|
||||
|
|
@ -67,7 +68,7 @@ impl<T: BoringHash> RustlsHkdf for Hkdf<T> {
|
|||
let digest = T::new_hash();
|
||||
let hash_size = digest.size();
|
||||
|
||||
let mut prk = [0u8; boring_sys::EVP_MAX_MD_SIZE as usize];
|
||||
let mut prk = Zeroizing::new([0u8; boring_sys::EVP_MAX_MD_SIZE as usize]);
|
||||
let mut prk_len = 0;
|
||||
|
||||
// if salt isn't set we usen these bytes here as salt
|
||||
|
|
@ -103,7 +104,7 @@ impl<T: BoringHash> RustlsHkdf for Hkdf<T> {
|
|||
okm: &rustls::crypto::tls13::OkmBlock,
|
||||
) -> Box<dyn rustls::crypto::tls13::HkdfExpander> {
|
||||
let okm = okm.as_ref();
|
||||
let mut prk = [0u8; boring_sys::EVP_MAX_MD_SIZE as usize];
|
||||
let mut prk = Zeroizing::new([0u8; boring_sys::EVP_MAX_MD_SIZE as usize]);
|
||||
let prk_len = okm.len();
|
||||
|
||||
prk[..prk_len].copy_from_slice(okm);
|
||||
|
|
@ -121,7 +122,7 @@ impl<T: BoringHash> RustlsHkdf for Hkdf<T> {
|
|||
message: &[u8],
|
||||
) -> rustls::crypto::hmac::Tag {
|
||||
let digest = T::new_hash();
|
||||
let mut hash = [0u8; boring_sys::EVP_MAX_MD_SIZE as usize];
|
||||
let mut hash = Zeroizing::new([0u8; boring_sys::EVP_MAX_MD_SIZE as usize]);
|
||||
let mut hash_len = 0u32;
|
||||
unsafe {
|
||||
cvt_p(boring_sys::HMAC(
|
||||
|
|
@ -140,7 +141,7 @@ impl<T: BoringHash> RustlsHkdf for Hkdf<T> {
|
|||
}
|
||||
|
||||
struct HkdfExpander {
|
||||
prk: [u8; boring_sys::EVP_MAX_MD_SIZE as usize],
|
||||
prk: Zeroizing<[u8; boring_sys::EVP_MAX_MD_SIZE as usize]>,
|
||||
prk_len: usize,
|
||||
digest: MessageDigest,
|
||||
}
|
||||
|
|
@ -187,7 +188,7 @@ impl tls13::HkdfExpander for HkdfExpander {
|
|||
/// This is infallible, because by definition `OkmBlock` is always exactly
|
||||
/// `HashLen` bytes long.
|
||||
fn expand_block(&self, info: &[&[u8]]) -> tls13::OkmBlock {
|
||||
let mut output = [0u8; boring_sys::EVP_MAX_MD_SIZE as usize];
|
||||
let mut output = Zeroizing::new([0u8; boring_sys::EVP_MAX_MD_SIZE as usize]);
|
||||
let output_len = self.hash_len();
|
||||
|
||||
self.expand_slice(info, &mut output[..output_len])
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use boring::hash::MessageDigest;
|
|||
use boring_additions::hmac::HmacCtx;
|
||||
use foreign_types::ForeignType;
|
||||
use rustls::crypto;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use crate::helper::{cvt, cvt_p};
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ impl crypto::hmac::Hmac for BoringHmac {
|
|||
Box::new(BoringHmacKey {
|
||||
ctx,
|
||||
md,
|
||||
key: key.to_vec(),
|
||||
key: Zeroizing::new(key.to_vec()),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -41,11 +42,10 @@ impl crypto::hmac::Hmac for BoringHmac {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct BoringHmacKey {
|
||||
ctx: HmacCtx,
|
||||
md: MessageDigest,
|
||||
key: Vec<u8>,
|
||||
key: Zeroizing<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl BoringHmacKey {
|
||||
|
|
@ -99,8 +99,8 @@ impl crypto::hmac::Key for BoringHmacKey {
|
|||
|
||||
self.update(last);
|
||||
|
||||
let mut out = [0u8; 32];
|
||||
let out_len = self.finish(&mut out);
|
||||
let mut out = Zeroizing::new([0u8; boring_sys::EVP_MAX_MD_SIZE as usize]);
|
||||
let out_len = self.finish(&mut out[..]);
|
||||
|
||||
crypto::hmac::Tag::new(&out[..out_len])
|
||||
}
|
||||
|
|
@ -112,7 +112,7 @@ impl crypto::hmac::Key for BoringHmacKey {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::SHA256;
|
||||
use super::{SHA256, SHA384};
|
||||
use hex_literal::hex;
|
||||
|
||||
#[test]
|
||||
|
|
@ -141,4 +141,23 @@ mod tests {
|
|||
hex!("11fa4a6ee97bebfad9e1087145c556fec9a786cad0659aa10702d21bd2968305")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha384_hmac_len() {
|
||||
let hasher = SHA384.with_key("Very Secret".as_bytes());
|
||||
|
||||
let tag = hasher.sign_concat(
|
||||
&[],
|
||||
&[
|
||||
"yay".as_bytes(),
|
||||
"this".as_bytes(),
|
||||
"works".as_bytes(),
|
||||
"well".as_bytes(),
|
||||
],
|
||||
&[],
|
||||
);
|
||||
|
||||
assert_eq!(tag.as_ref().len(), hasher.tag_len());
|
||||
assert_eq!(tag.as_ref().len(), 48);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ impl crypto::ActiveKeyExchange for KeyExchange {
|
|||
peer_pub_key: &[u8],
|
||||
) -> Result<crypto::SharedSecret, rustls::Error> {
|
||||
self.diffie_hellman(peer_pub_key)
|
||||
.map(|x| crypto::SharedSecret::from(x.as_slice()))
|
||||
.map(crypto::SharedSecret::from)
|
||||
.map_err(|e| {
|
||||
log_and_map(
|
||||
"ex::KeyExchange::diffie_hellman",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue