use crate::error::Result;
use crate::mechanism::DRBG;
use crate::ossl::common::osslctx;
use crate::pkcs11::{CKR_ARGUMENTS_BAD, CKR_RANDOM_NO_RNG};
use ossl::digest::DigestAlg;
use ossl::rand::{EvpRandCtx, EvpRandGetParam};
#[derive(Debug)]
pub struct HmacDrbg {
ctx: EvpRandCtx,
min_entropy: usize,
max_entropy: usize,
max_addin: usize,
}
impl HmacDrbg {
pub fn new(hash: &str) -> Result<HmacDrbg> {
let digest = match hash {
"HMAC DRBG SHA256" => DigestAlg::Sha2_256,
"HMAC DRBG SHA512" => DigestAlg::Sha2_512,
_ => return Err(CKR_RANDOM_NO_RNG)?,
};
let ctx =
EvpRandCtx::new_hmac_drbg(osslctx(), digest, hash.as_bytes())?;
let mut min_entropy = 0;
let mut max_entropy = 0;
let mut max_addin = 0;
let mut params = [
EvpRandGetParam::MinEntropyLen(0),
EvpRandGetParam::MaxEntropyLen(0),
EvpRandGetParam::MaxAdinLen(0),
];
if ctx.get_ctx_params(&mut params).is_ok() {
if let EvpRandGetParam::MinEntropyLen(val) = ¶ms[0] {
min_entropy = *val;
}
if let EvpRandGetParam::MaxEntropyLen(val) = ¶ms[1] {
max_entropy = *val;
}
if let EvpRandGetParam::MaxAdinLen(val) = ¶ms[2] {
max_addin = *val;
}
}
Ok(HmacDrbg {
ctx,
min_entropy,
max_entropy,
max_addin,
})
}
}
impl DRBG for HmacDrbg {
fn reseed(&mut self, entropy: &[u8], addtl: &[u8]) -> Result<()> {
if entropy.len() < self.min_entropy {
return Err(CKR_ARGUMENTS_BAD)?;
}
if self.max_entropy > 0 && entropy.len() > self.max_entropy {
return Err(CKR_ARGUMENTS_BAD)?;
}
if self.max_addin > 0 && addtl.len() > self.max_addin {
return Err(CKR_ARGUMENTS_BAD)?;
}
Ok(self.ctx.reseed(entropy, addtl)?)
}
fn generate(&mut self, addtl: &[u8], output: &mut [u8]) -> Result<()> {
Ok(self.ctx.generate(addtl, output)?)
}
}
unsafe impl Send for HmacDrbg {}
unsafe impl Sync for HmacDrbg {}