Skip to content

Commit 879da27

Browse files
authored
Merge pull request parallaxsecond#239 from hug-dev/memory
Add memory zeroizing when needed
2 parents 3ea3461 + 3090a13 commit 879da27

File tree

7 files changed

+54
-22
lines changed

7 files changed

+54
-22
lines changed

src/key_info_managers/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use parsec_interface::operations::psa_key_attributes::Attributes;
1212
use parsec_interface::requests::{ProviderID, ResponseStatus};
1313
use serde::{Deserialize, Serialize};
1414
use std::fmt;
15+
use zeroize::Zeroize;
1516

1617
pub mod on_disk_manager;
1718

@@ -53,7 +54,8 @@ impl fmt::Display for KeyTriple {
5354
}
5455

5556
/// Information stored about a key
56-
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
57+
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Zeroize)]
58+
#[zeroize(drop)]
5759
pub struct KeyInfo {
5860
/// Reference to a key in the Provider
5961
pub id: Vec<u8>,

src/providers/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use log::trace;
1010
use parsec_interface::requests::{Opcode, ProviderID};
1111
use serde::Deserialize;
1212
use std::collections::HashSet;
13+
use zeroize::Zeroize;
1314

1415
pub mod core_provider;
1516

@@ -27,7 +28,8 @@ pub mod tpm_provider;
2728
/// to the one described in the Internally Tagged Enum representation
2829
/// where "provider_type" is the tag field. For details see:
2930
/// https://serde.rs/enum-representations.html
30-
#[derive(Deserialize, Debug)]
31+
#[derive(Deserialize, Debug, Zeroize)]
32+
#[zeroize(drop)]
3133
#[serde(tag = "provider_type")]
3234
pub enum ProviderConfig {
3335
/// Mbed Crypto provider configuration
@@ -57,21 +59,19 @@ pub enum ProviderConfig {
5759
},
5860
}
5961

60-
use self::ProviderConfig::{MbedCrypto, Pkcs11, Tpm};
61-
6262
impl ProviderConfig {
6363
/// Get the name of the Key Info Manager in the provider configuration
6464
pub fn key_info_manager(&self) -> &String {
6565
match *self {
66-
MbedCrypto {
66+
ProviderConfig::MbedCrypto {
6767
ref key_info_manager,
6868
..
6969
} => key_info_manager,
70-
Pkcs11 {
70+
ProviderConfig::Pkcs11 {
7171
ref key_info_manager,
7272
..
7373
} => key_info_manager,
74-
Tpm {
74+
ProviderConfig::Tpm {
7575
ref key_info_manager,
7676
..
7777
} => key_info_manager,
@@ -80,9 +80,9 @@ impl ProviderConfig {
8080
/// Get the Provider ID of the provider
8181
pub fn provider_id(&self) -> ProviderID {
8282
match *self {
83-
MbedCrypto { .. } => ProviderID::MbedCrypto,
84-
Pkcs11 { .. } => ProviderID::Pkcs11,
85-
Tpm { .. } => ProviderID::Tpm,
83+
ProviderConfig::MbedCrypto { .. } => ProviderID::MbedCrypto,
84+
ProviderConfig::Pkcs11 { .. } => ProviderID::Pkcs11,
85+
ProviderConfig::Tpm { .. } => ProviderID::Tpm,
8686
}
8787
}
8888
}

src/providers/pkcs11_provider/mod.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ use parsec_interface::operations::{
1515
psa_generate_key, psa_import_key, psa_sign_hash, psa_verify_hash,
1616
};
1717
use parsec_interface::requests::{Opcode, ProviderID, ResponseStatus, Result};
18+
use parsec_interface::secrecy::SecretString;
1819
use pkcs11::types::{CKF_OS_LOCKING_OK, CK_C_INITIALIZE_ARGS, CK_SLOT_ID};
1920
use pkcs11::Ctx;
2021
use std::collections::HashSet;
2122
use std::io::{Error, ErrorKind};
23+
use std::str::FromStr;
2224
use std::sync::{Arc, Mutex, RwLock};
2325
use utils::{KeyPairType, ReadWriteSession, Session};
2426
use uuid::Uuid;
27+
use zeroize::Zeroize;
2528

2629
type LocalIdStore = HashSet<[u8; 4]>;
2730

@@ -66,7 +69,7 @@ pub struct Pkcs11Provider {
6669
backend: Ctx,
6770
slot_number: CK_SLOT_ID,
6871
// Some PKCS 11 devices do not need a pin, the None variant means that.
69-
user_pin: Option<String>,
72+
user_pin: Option<SecretString>,
7073
}
7174

7275
impl Pkcs11Provider {
@@ -78,7 +81,7 @@ impl Pkcs11Provider {
7881
key_info_store: Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>,
7982
backend: Ctx,
8083
slot_number: usize,
81-
user_pin: Option<String>,
84+
user_pin: Option<SecretString>,
8285
) -> Option<Pkcs11Provider> {
8386
#[allow(clippy::mutex_atomic)]
8487
let pkcs11_provider = Pkcs11Provider {
@@ -275,18 +278,24 @@ impl Drop for Pkcs11Provider {
275278
if let Err(e) = self.backend.finalize() {
276279
format_error!("Error when dropping the PKCS 11 provider", e);
277280
}
281+
// The other fields containing confidential information should implement zeroizing on drop.
282+
self.slot_number.zeroize();
278283
}
279284
}
280285

281286
/// Builder for Pkcs11Provider
287+
///
288+
/// This builder contains some confidential information that is passed to the Pkcs11Provider. The
289+
/// Pkcs11Provider will zeroize this data when dropping. This data will not be cloned when
290+
/// building.
282291
#[derive(Default, Derivative)]
283292
#[derivative(Debug)]
284293
pub struct Pkcs11ProviderBuilder {
285294
#[derivative(Debug = "ignore")]
286295
key_info_store: Option<Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>>,
287296
pkcs11_library_path: Option<String>,
288297
slot_number: Option<usize>,
289-
user_pin: Option<String>,
298+
user_pin: Option<SecretString>,
290299
}
291300

292301
impl Pkcs11ProviderBuilder {
@@ -328,8 +337,13 @@ impl Pkcs11ProviderBuilder {
328337
}
329338

330339
/// Specify the user pin
331-
pub fn with_user_pin(mut self, user_pin: Option<String>) -> Pkcs11ProviderBuilder {
332-
self.user_pin = user_pin;
340+
pub fn with_user_pin(mut self, mut user_pin: Option<String>) -> Pkcs11ProviderBuilder {
341+
self.user_pin = match user_pin {
342+
// The conversion form a String is infallible.
343+
Some(ref pin) => Some(SecretString::from_str(&pin).unwrap()),
344+
None => None,
345+
};
346+
user_pin.zeroize();
333347

334348
self
335349
}

src/providers/pkcs11_provider/utils.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ use parsec_interface::operations::psa_algorithm::*;
77
use parsec_interface::operations::psa_key_attributes::*;
88
use parsec_interface::requests::ResponseStatus;
99
use parsec_interface::requests::Result;
10+
use parsec_interface::secrecy::ExposeSecret;
1011
use picky_asn1_x509::{AlgorithmIdentifier, DigestInfo, SHAVariant};
1112
use pkcs11::errors::Error;
1213
use pkcs11::types::*;
1314
use pkcs11::types::{CKF_RW_SESSION, CKF_SERIAL_SESSION, CKU_USER};
1415
use std::convert::{TryFrom, TryInto};
1516
use std::pin::Pin;
17+
use zeroize::Zeroize;
1618

1719
// Public exponent value for all RSA keys.
1820
const PUBLIC_EXPONENT: [u8; 3] = [0x01, 0x00, 0x01];
@@ -335,7 +337,8 @@ pub struct Session<'a> {
335337
is_logged_in: bool,
336338
}
337339

338-
#[derive(PartialEq)]
340+
#[derive(PartialEq, Zeroize)]
341+
#[zeroize(drop)]
339342
pub enum ReadWriteSession {
340343
ReadOnly,
341344
ReadWrite,
@@ -417,11 +420,11 @@ impl Session<'_> {
417420
Ok(())
418421
} else if let Some(user_pin) = self.provider.user_pin.as_ref() {
419422
trace!("Login command");
420-
match self
421-
.provider
422-
.backend
423-
.login(self.session_handle, CKU_USER, Some(user_pin))
424-
{
423+
match self.provider.backend.login(
424+
self.session_handle,
425+
CKU_USER,
426+
Some(user_pin.expose_secret()),
427+
) {
425428
Ok(_) => {
426429
if crate::utils::GlobalConfig::log_error_details() {
427430
info!("Logging in session {}.", self.session_handle);
@@ -517,6 +520,8 @@ impl Drop for Session<'_> {
517520
}
518521
}
519522
}
523+
self.session_handle.zeroize();
524+
self.is_logged_in.zeroize();
520525
}
521526
}
522527

src/providers/tpm_provider/key_management.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use parsec_interface::operations::{
1515
use parsec_interface::requests::{ProviderID, ResponseStatus, Result};
1616
use parsec_interface::secrecy::ExposeSecret;
1717
use picky_asn1_x509::RSAPublicKey;
18+
use zeroize::Zeroize;
1819

1920
// Public exponent value for all RSA keys.
2021
const PUBLIC_EXPONENT: [u8; 3] = [0x01, 0x00, 0x01];
@@ -24,7 +25,7 @@ const AUTH_VAL_LEN: usize = 32;
2425
fn insert_password_context(
2526
store_handle: &mut dyn ManageKeyInfo,
2627
key_triple: KeyTriple,
27-
password_context: PasswordContext,
28+
mut password_context: PasswordContext,
2829
key_attributes: Attributes,
2930
) -> Result<()> {
3031
let error_storing = |e| Err(key_info_managers::to_response_status(e));
@@ -34,6 +35,8 @@ fn insert_password_context(
3435
attributes: key_attributes,
3536
};
3637

38+
password_context.auth_value.zeroize();
39+
3740
if store_handle
3841
.insert(key_triple, key_info)
3942
.or_else(error_storing)?

src/providers/tpm_provider/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use std::sync::{Arc, Mutex, RwLock};
2222
use tss_esapi::constants::algorithm::{Cipher, HashingAlgorithm};
2323
use tss_esapi::Tcti;
2424
use uuid::Uuid;
25+
use zeroize::Zeroize;
2526

2627
mod asym_encryption;
2728
mod asym_sign;
@@ -171,6 +172,10 @@ impl Drop for TpmProvider {
171172
}
172173

173174
/// Builder for TpmProvider
175+
///
176+
/// This builder contains some confidential information that is passed to the TpmProvider. The
177+
/// TpmProvider will zeroize this data when dropping. This data will not be cloned when
178+
/// building.
174179
#[derive(Default, Derivative)]
175180
#[derivative(Debug)]
176181
pub struct TpmProviderBuilder {
@@ -284,6 +289,8 @@ impl TpmProviderBuilder {
284289
.map_err(|_| {
285290
std::io::Error::new(ErrorKind::InvalidData, "Invalid TCTI configuration string")
286291
})?;
292+
self.tcti.zeroize();
293+
self.owner_hierarchy_auth.zeroize();
287294
TpmProvider::new(
288295
self.key_info_store.ok_or_else(|| {
289296
std::io::Error::new(ErrorKind::InvalidData, "missing key info store")

src/providers/tpm_provider/utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub fn to_response_status(error: Error) -> ResponseStatus {
9090
#[derive(Serialize, Deserialize)]
9191
pub struct PasswordContext {
9292
pub context: TpmsContext,
93+
/// This value is confidential and needs to be zeroized by its new owner.
9394
pub auth_value: Vec<u8>,
9495
}
9596

0 commit comments

Comments
 (0)