Skip to content

Commit

Permalink
Replace Zeroize with OPENSSL_cleanse
Browse files Browse the repository at this point in the history
The Zeroize crate performance is crazy slow.
The search for a performance issue with the nssdb storage via
valgrind's callgrind revelead that 50% of the time in the HMAC code was
spent on zeroization because of the way the Zeroize crate is built.

Replace it everywhere with a simpler zeromem function that underneath
simply calls OPENSSL_cleanse() on the mutable slice passed in.

With this change alone the new test that performs 100 pbkdf2 calls went
from ~9s to ~4.5s on my laptop.

Signed-off-by: Simo Sorce <[email protected]>
  • Loading branch information
simo5 committed Dec 19, 2024
1 parent c46fb72 commit 9af34b5
Show file tree
Hide file tree
Showing 17 changed files with 70 additions and 69 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ serde_json = "1.0.104"
serial_test = "3.1.1"
toml = { version = "0.8.19", default-features = false, features = ["display", "parse"] }
uuid = { version = "1.4.1", features = ["v4"] }
zeroize = "1.6.0"

[features]
aes = []
Expand Down
7 changes: 3 additions & 4 deletions src/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ use crate::attribute::Attribute;
use crate::error::Result;
use crate::interface::*;
use crate::mechanism::*;
use crate::misc::zeromem;
use crate::object::*;
use crate::ossl::aes::*;
use crate::{attr_element, cast_params};

use once_cell::sync::Lazy;

use zeroize::Zeroize;

pub const MIN_AES_SIZE_BYTES: usize = 16; /* 128 bits */
pub const MID_AES_SIZE_BYTES: usize = 24; /* 192 bits */
pub const MAX_AES_SIZE_BYTES: usize = 32; /* 256 bits */
Expand Down Expand Up @@ -100,7 +99,7 @@ impl ObjectFactory for AesKeyFactory {
Some(idx) => {
let len = usize::try_from(template[idx].to_ulong()?)?;
if len > data.len() {
data.zeroize();
zeromem(data.as_mut_slice());
return Err(CKR_KEY_SIZE_RANGE)?;
}
if len < data.len() {
Expand All @@ -112,7 +111,7 @@ impl ObjectFactory for AesKeyFactory {
match check_key_len(data.len()) {
Ok(_) => (),
Err(e) => {
data.zeroize();
zeromem(data.as_mut_slice());
return Err(e);
}
}
Expand Down
7 changes: 3 additions & 4 deletions src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ use std::borrow::Cow;

use crate::error::{Error, Result};
use crate::interface::*;
use crate::misc::zeromem;
use crate::{bytes_to_vec, sizeof, void_ptr};

use zeroize::Zeroize;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AttrType {
BoolType,
Expand Down Expand Up @@ -271,7 +270,7 @@ impl Attribute {
}

pub fn zeroize(&mut self) {
self.value.zeroize();
zeromem(self.value.as_mut_slice());
}

pub fn from_date_bytes(t: CK_ULONG, val: Vec<u8>) -> Attribute {
Expand Down Expand Up @@ -559,7 +558,7 @@ impl Drop for CkAttrs<'_> {
fn drop(&mut self) {
if self.zeroize {
while let Some(mut elem) = self.v.pop() {
elem.zeroize();
zeromem(elem.as_mut_slice());
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use crate::error::{Error, Result};
use crate::hash;
use crate::interface::*;
use crate::mechanism::*;
use crate::misc::zeromem;
use crate::object::*;
use crate::sizeof;

use once_cell::sync::Lazy;
use zeroize::Zeroize;

#[cfg(not(feature = "fips"))]
use crate::native::hmac::HMACOperation;
Expand All @@ -26,7 +26,7 @@ pub struct HmacKey {

impl Drop for HmacKey {
fn drop(&mut self) {
self.raw.zeroize()
zeromem(self.raw.as_mut_slice())
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/kasn1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use std::borrow::Cow;

use crate::error::Result;
use crate::interface::*;
use crate::misc::zeromem;

use asn1;
use zeroize::Zeroize;

/* Helper routines to use with rust/asn1 */

Expand Down Expand Up @@ -68,7 +68,7 @@ impl<'a> DerEncBigUint<'a> {
impl Drop for DerEncBigUint<'_> {
fn drop(&mut self) {
match &self.data {
Cow::Owned(_) => self.data.to_mut().zeroize(),
Cow::Owned(_) => zeromem(self.data.to_mut()),
_ => (),
}
}
Expand Down Expand Up @@ -111,7 +111,7 @@ impl<'a> DerEncOctetString<'a> {
impl Drop for DerEncOctetString<'_> {
fn drop(&mut self) {
match &self.data {
Cow::Owned(_) => self.data.to_mut().zeroize(),
Cow::Owned(_) => zeromem(self.data.to_mut()),
_ => (),
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::attribute::{Attribute, CkAttrs};
use crate::error::Result;
use crate::interface::*;
use crate::object::{Object, ObjectFactories, ObjectType};

use crate::ossl::common::zeromem as ossl_zeromem;
pub const CK_ULONG_SIZE: usize = std::mem::size_of::<CK_ULONG>();

#[macro_export]
Expand Down Expand Up @@ -191,3 +191,7 @@ pub fn copy_sized_string(s: &[u8], d: &mut [u8]) {
d[slen..].fill(0x20); /* space in ASCII/UTF8 */
}
}

pub fn zeromem(mem: &mut [u8]) {
ossl_zeromem(mem);
}
8 changes: 4 additions & 4 deletions src/native/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use crate::hash;
use crate::hmac::*;
use crate::interface::*;
use crate::mechanism::*;
use crate::misc::zeromem;

use constant_time_eq::constant_time_eq;
use zeroize::Zeroize;

/* HMAC spec From FIPS 198-1 */

Expand All @@ -32,9 +32,9 @@ pub struct HMACOperation {

impl Drop for HMACOperation {
fn drop(&mut self) {
self.state.zeroize();
self.ipad.zeroize();
self.opad.zeroize();
zeromem(self.state.as_mut_slice());
zeromem(self.ipad.as_mut_slice());
zeromem(self.opad.as_mut_slice());
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use crate::attribute::{AttrType, Attribute};
use crate::error::{Error, Result};
use crate::interface::*;
use crate::mechanism::{Mechanism, Mechanisms};
use crate::misc::zeromem;
use crate::CSPRNG;

use bitflags::bitflags;
use once_cell::sync::Lazy;
use uuid::Uuid;
use zeroize::Zeroize;

macro_rules! create_bool_checker {
(make $name:ident; from $id:expr; def $def:expr) => {
Expand Down Expand Up @@ -1032,7 +1032,7 @@ macro_rules! ok_or_clear {
match $exp {
Ok(x) => x,
Err(e) => {
$clear.zeroize();
zeromem($clear.as_mut_slice());
return Err(e);
}
}
Expand Down
42 changes: 21 additions & 21 deletions src/ossl/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::error;
use crate::error::Result;
use crate::interface::*;
use crate::mechanism::*;
use crate::misc::zeromem;
use crate::object::Object;
use crate::ossl::bindings::*;
use crate::ossl::common::*;
Expand All @@ -19,7 +20,6 @@ use crate::get_random_data;

use constant_time_eq::constant_time_eq;
use once_cell::sync::Lazy;
use zeroize::Zeroize;

const MAX_CCM_BUF: usize = 1 << 20; /* 1MiB */
const MIN_RANDOM_IV_BITS: usize = 64;
Expand Down Expand Up @@ -126,7 +126,7 @@ struct AesKey {

impl Drop for AesKey {
fn drop(&mut self) {
self.raw.zeroize()
zeromem(self.raw.as_mut_slice());
}
}

Expand Down Expand Up @@ -176,7 +176,7 @@ impl AesIvData {
}
impl Drop for AesIvData {
fn drop(&mut self) {
self.buf.zeroize();
zeromem(self.buf.as_mut_slice());
}
}

Expand All @@ -193,8 +193,8 @@ struct AesParams {
#[cfg(feature = "fips")]
impl AesParams {
fn zeroize(&mut self) {
self.iv.buf.zeroize();
self.aad.zeroize();
zeromem(self.iv.buf.as_mut_slice());
zeromem(self.aad.as_mut_slice());
}
}

Expand All @@ -215,7 +215,7 @@ pub struct AesOperation {

impl Drop for AesOperation {
fn drop(&mut self) {
self.finalbuf.zeroize()
zeromem(self.finalbuf.as_mut_slice());
}
}

Expand Down Expand Up @@ -944,7 +944,7 @@ impl AesOperation {
let mut op = match Self::encrypt_new(mech, wrapping_key) {
Ok(o) => o,
Err(e) => {
keydata.zeroize();
zeromem(keydata.as_mut_slice());
return Err(e);
}
};
Expand All @@ -967,7 +967,7 @@ impl AesOperation {
_ => (),
}
let result = op.encrypt(&keydata, output);
keydata.zeroize();
zeromem(keydata.as_mut_slice());
result
}

Expand Down Expand Up @@ -997,8 +997,8 @@ impl AesOperation {
) -> Result<CK_BYTE_PTR> {
#[cfg(feature = "fips")]
{
self.params.iv.buf.zeroize();
self.params.aad.zeroize();
zeromem(self.params.iv.buf.as_mut_slice());
zeromem(self.params.aad.as_mut_slice());
}
match self.mech {
CKM_AES_CCM => {
Expand Down Expand Up @@ -1277,7 +1277,7 @@ impl AesOperation {
#[cfg(feature = "fips")]
{
self.params.zeroize();
self.finalbuf.zeroize();
zeromem(self.finalbuf.as_mut_slice());
}
self.finalized = false;
self.in_use = true;
Expand Down Expand Up @@ -1343,7 +1343,7 @@ impl AesOperation {
#[cfg(feature = "fips")]
{
self.params.zeroize();
self.finalbuf.zeroize();
zeromem(self.finalbuf.as_mut_slice());
}
self.finalized = false;
self.in_use = true;
Expand Down Expand Up @@ -1523,7 +1523,7 @@ impl Encryption for AesOperation {
}
if self.mech == CKM_AES_CCM {
if plain_len > 0 && plain_buf == self.finalbuf.as_ptr() {
self.finalbuf.zeroize();
zeromem(self.finalbuf.as_mut_slice());
self.finalbuf.clear();
}
}
Expand Down Expand Up @@ -2274,11 +2274,11 @@ impl MsgEncryption for AesOperation {
)
};
if res != 1 {
cipher.zeroize();
zeromem(cipher);
return Err(self.op_err(CKR_DEVICE_ERROR));
}
if outl != 0 {
cipher.zeroize();
zeromem(cipher);
return Err(self.op_err(CKR_DEVICE_ERROR));
}
let res = unsafe {
Expand All @@ -2290,7 +2290,7 @@ impl MsgEncryption for AesOperation {
)
};
if res != 1 {
cipher.zeroize();
zeromem(cipher);
return Err(self.op_err(CKR_DEVICE_ERROR));
}

Expand Down Expand Up @@ -2469,11 +2469,11 @@ impl MsgDecryption for AesOperation {
)
};
if res != 1 {
plain.zeroize();
zeromem(plain);
return Err(self.op_err(CKR_ENCRYPTED_DATA_INVALID));
}
if outl != 0 {
plain.zeroize();
zeromem(plain);
return Err(self.op_err(CKR_DEVICE_ERROR));
}

Expand Down Expand Up @@ -2629,7 +2629,7 @@ impl AesCmacOperation {
}

output.copy_from_slice(&buf[..output.len()]);
buf.zeroize();
zeromem(&mut buf);

#[cfg(feature = "fips")]
{
Expand Down Expand Up @@ -2740,8 +2740,8 @@ pub struct AesMacOperation {

impl Drop for AesMacOperation {
fn drop(&mut self) {
self.padbuf.zeroize();
self.macbuf.zeroize();
zeromem(&mut self.padbuf);
zeromem(&mut self.macbuf);
}
}

Expand Down
9 changes: 7 additions & 2 deletions src/ossl/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use crate::ossl::montgomery as ecm;
use crate::ossl::rsa;

use asn1;
use zeroize::Zeroize;

macro_rules! ptr_wrapper_struct {
($name:ident; $ctx:ident) => {
Expand Down Expand Up @@ -367,7 +366,7 @@ impl Drop for OsslParam<'_> {
fn drop(&mut self) {
if self.zeroize {
while let Some(mut elem) = self.v.pop() {
elem.zeroize();
zeromem(elem.as_mut_slice());
}
}
}
Expand Down Expand Up @@ -892,3 +891,9 @@ fn oid_to_ossl_name(oid: &asn1::ObjectIdentifier) -> Result<&'static [u8]> {
pub fn get_ossl_name_from_obj(key: &Object) -> Result<&'static [u8]> {
oid_to_ossl_name(&get_oid_from_obj(key)?)
}

pub fn zeromem(mem: &mut [u8]) {
unsafe {
OPENSSL_cleanse(void_ptr!(mem.as_mut_ptr()), mem.len());
}
}
Loading

0 comments on commit 9af34b5

Please sign in to comment.