Skip to content

Commit 881a615

Browse files
authored
Merge pull request #32 from ionut-arm/secrecy
Add memory wiping functionality
2 parents d2ba219 + 7c379a3 commit 881a615

File tree

6 files changed

+57
-36
lines changed

6 files changed

+57
-36
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ edition = "2018"
1313
documentation = "https://docs.rs/crate/parsec-client"
1414

1515
[dependencies]
16-
parsec-interface = "0.15.0"
16+
parsec-interface = "0.17.0"
1717
num = "0.2.1"
1818
rand = "0.7.3"
1919
log = "0.4.8"
2020
derivative = "2.1.1"
2121
uuid = "0.7.4"
22+
zeroize = "1.1.0"
2223

2324
[dev-dependencies]
2425
mockstream = "0.0.3"

src/auth.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22
// SPDX-License-Identifier: Apache-2.0
33
//! Client app authentication data
44
use parsec_interface::requests::{request::RequestAuth, AuthType};
5+
use parsec_interface::secrecy::{ExposeSecret, Secret};
56

67
/// Authentication data used in Parsec requests
78
#[derive(Clone, Debug)]
89
pub enum AuthenticationData {
910
/// Used in cases where no authentication is desired or required
1011
None,
1112
/// Data used for direct, identity-based authentication
12-
AppIdentity(String),
13+
///
14+
/// The app name is wrapped in a [`Secret`](https://docs.rs/secrecy/*/secrecy/struct.Secret.html).
15+
/// The `Secret` struct can be imported from
16+
/// `parsec_client::core::secrecy::Secret`.
17+
AppIdentity(Secret<String>),
1318
}
1419

1520
impl AuthenticationData {
@@ -25,9 +30,9 @@ impl AuthenticationData {
2530
impl From<&AuthenticationData> for RequestAuth {
2631
fn from(data: &AuthenticationData) -> Self {
2732
match data {
28-
AuthenticationData::None => Default::default(),
33+
AuthenticationData::None => RequestAuth::new(Vec::new()),
2934
AuthenticationData::AppIdentity(name) => {
30-
RequestAuth::from_bytes(name.bytes().collect())
35+
RequestAuth::new(name.expose_secret().bytes().collect())
3136
}
3237
}
3338
}

src/core/basic_client.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ use parsec_interface::operations::psa_sign_hash::Operation as PsaSignHash;
1717
use parsec_interface::operations::psa_verify_hash::Operation as PsaVerifyHash;
1818
use parsec_interface::operations::{NativeOperation, NativeResult};
1919
use parsec_interface::requests::{Opcode, ProviderID};
20+
use parsec_interface::secrecy::Secret;
2021
use std::collections::HashSet;
22+
use zeroize::Zeroizing;
2123

2224
/// Core client for Parsec service
2325
///
@@ -37,9 +39,10 @@ use std::collections::HashSet;
3739
///```no_run
3840
///use parsec_client::auth::AuthenticationData;
3941
///use parsec_client::BasicClient;
42+
///use parsec_client::core::secrecy::Secret;
4043
///
4144
///let app_name = String::from("app-name");
42-
///let app_auth_data = AuthenticationData::AppIdentity(app_name);
45+
///let app_auth_data = AuthenticationData::AppIdentity(Secret::new(app_name));
4346
///let client: BasicClient = BasicClient::new(app_auth_data);
4447
///```
4548
///
@@ -49,8 +52,9 @@ use std::collections::HashSet;
4952
///```no_run
5053
///# use parsec_client::auth::AuthenticationData;
5154
///# use parsec_client::BasicClient;
55+
///# use parsec_client::core::secrecy::Secret;
5256
///# use parsec_client::core::interface::requests::ProviderID;
53-
///# let client: BasicClient = BasicClient::new(AuthenticationData::AppIdentity(String::from("app-name")));
57+
///# let client: BasicClient = BasicClient::new(AuthenticationData::AppIdentity(Secret::new(String::from("app-name"))));
5458
///let res = client.ping();
5559
///
5660
///if let Ok((wire_prot_v_maj, wire_prot_v_min)) = res {
@@ -71,8 +75,9 @@ use std::collections::HashSet;
7175
///```no_run
7276
///# use parsec_client::auth::AuthenticationData;
7377
///# use parsec_client::BasicClient;
78+
///# use parsec_client::core::secrecy::Secret;
7479
///# use parsec_client::core::interface::requests::ProviderID;
75-
///# let client: BasicClient = BasicClient::new(AuthenticationData::AppIdentity(String::from("app-name")));
80+
///# let client: BasicClient = BasicClient::new(AuthenticationData::AppIdentity(Secret::new(String::from("app-name"))));
7681
///use uuid::Uuid;
7782
///
7883
///// Identify provider by its UUID (in this case, the PKCS11 provider)
@@ -94,7 +99,8 @@ use std::collections::HashSet;
9499
///# use parsec_client::auth::AuthenticationData;
95100
///# use parsec_client::BasicClient;
96101
///# use parsec_client::core::interface::requests::ProviderID;
97-
///# let mut client: BasicClient = BasicClient::new(AuthenticationData::AppIdentity(String::from("app-name")));
102+
///# use parsec_client::core::secrecy::Secret;
103+
///# let mut client: BasicClient = BasicClient::new(AuthenticationData::AppIdentity(Secret::new(String::from("app-name"))));
98104
///use parsec_client::core::interface::requests::Opcode;
99105
///
100106
///let desired_provider = ProviderID::Pkcs11;
@@ -114,8 +120,9 @@ use std::collections::HashSet;
114120
///```no_run
115121
///# use parsec_client::auth::AuthenticationData;
116122
///# use parsec_client::BasicClient;
123+
///# use parsec_client::core::secrecy::Secret;
117124
///# use parsec_client::core::interface::requests::ProviderID;
118-
///# let client: BasicClient = BasicClient::new(AuthenticationData::AppIdentity(String::from("app-name")));
125+
///# let client: BasicClient = BasicClient::new(AuthenticationData::AppIdentity(Secret::new(String::from("app-name"))));
119126
///use parsec_client::core::interface::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash};
120127
///use parsec_client::core::interface::operations::psa_key_attributes::{Attributes, Lifetime, Policy, Type, UsageFlags};
121128
///
@@ -151,7 +158,7 @@ use std::collections::HashSet;
151158
///};
152159
///
153160
///client
154-
/// .psa_generate_key(key_name, key_attrs)
161+
/// .psa_generate_key(key_name.clone(), key_attrs)
155162
/// .expect("Failed to create key!");
156163
///```
157164
#[derive(Debug)]
@@ -356,9 +363,10 @@ impl BasicClient {
356363
pub fn psa_import_key(
357364
&self,
358365
key_name: String,
359-
key_material: Vec<u8>,
366+
key_material: &[u8],
360367
key_attributes: Attributes,
361368
) -> Result<()> {
369+
let key_material = Secret::new(key_material.to_vec());
362370
let crypto_provider = self.can_provide_crypto()?;
363371

364372
let op = PsaImportKey {
@@ -405,7 +413,7 @@ impl BasicClient {
405413
)?;
406414

407415
if let NativeResult::PsaExportPublicKey(res) = res {
408-
Ok(res.data)
416+
Ok(res.data.to_vec())
409417
} else {
410418
// Should really not be reached given the checks we do, but it's not impossible if some
411419
// changes happen in the interface
@@ -438,9 +446,10 @@ impl BasicClient {
438446
pub fn psa_sign_hash(
439447
&self,
440448
key_name: String,
441-
hash: Vec<u8>,
449+
hash: &[u8],
442450
sign_algorithm: AsymmetricSignature,
443451
) -> Result<Vec<u8>> {
452+
let hash = Zeroizing::new(hash.to_vec());
444453
let crypto_provider = self.can_provide_crypto()?;
445454

446455
let op = PsaSignHash {
@@ -456,7 +465,7 @@ impl BasicClient {
456465
)?;
457466

458467
if let NativeResult::PsaSignHash(res) = res {
459-
Ok(res.signature)
468+
Ok(res.signature.to_vec())
460469
} else {
461470
// Should really not be reached given the checks we do, but it's not impossible if some
462471
// changes happen in the interface
@@ -489,10 +498,12 @@ impl BasicClient {
489498
pub fn psa_verify_hash(
490499
&self,
491500
key_name: String,
492-
hash: Vec<u8>,
501+
hash: &[u8],
493502
sign_algorithm: AsymmetricSignature,
494-
signature: Vec<u8>,
503+
signature: &[u8],
495504
) -> Result<()> {
505+
let hash = Zeroizing::new(hash.to_vec());
506+
let signature = Zeroizing::new(signature.to_vec());
496507
let crypto_provider = self.can_provide_crypto()?;
497508

498509
let op = PsaVerifyHash {

src/core/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ pub mod operation_client;
1212
pub mod request_client;
1313
mod testing;
1414

15+
/// Resurfacing of the Secrecy library used by the client.
16+
pub use interface::secrecy;
17+
/// Resurfacing of the Parsec interface library used by the client.
1518
pub use parsec_interface as interface;

src/core/testing/core_tests.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use parsec_interface::requests::Response;
1717
use parsec_interface::requests::ResponseStatus;
1818
use parsec_interface::requests::{request::RequestHeader, Request};
1919
use parsec_interface::requests::{AuthType, BodyType, Opcode};
20+
use parsec_interface::secrecy::{ExposeSecret, Secret};
2021
use std::collections::HashSet;
2122
use std::io::ErrorKind;
2223

@@ -118,7 +119,9 @@ fn list_opcodes_test() {
118119

119120
#[test]
120121
fn no_crypto_provider_test() {
121-
let client = BasicClient::new(AuthenticationData::AppIdentity(String::from("oops")));
122+
let client = BasicClient::new(AuthenticationData::AppIdentity(Secret::new(String::from(
123+
"oops",
124+
))));
122125

123126
let res = client
124127
.psa_destroy_key(String::from("random key"))
@@ -129,7 +132,9 @@ fn no_crypto_provider_test() {
129132

130133
#[test]
131134
fn core_provider_for_crypto_test() {
132-
let mut client = BasicClient::new(AuthenticationData::AppIdentity(String::from("oops")));
135+
let mut client = BasicClient::new(AuthenticationData::AppIdentity(Secret::new(String::from(
136+
"oops",
137+
))));
133138

134139
client.set_implicit_provider(ProviderID::Core);
135140
let res = client
@@ -168,7 +173,7 @@ fn psa_generate_key_test() {
168173
};
169174

170175
client
171-
.psa_generate_key(key_name.clone(), key_attrs.clone())
176+
.psa_generate_key(key_name.clone(), key_attrs)
172177
.expect("failed to generate key");
173178

174179
// Check request:
@@ -236,15 +241,15 @@ fn psa_import_key_test() {
236241
};
237242
let key_data = vec![0xff_u8; 128];
238243
client
239-
.psa_import_key(key_name.clone(), key_data.clone(), key_attrs.clone())
244+
.psa_import_key(key_name.clone(), &key_data, key_attrs)
240245
.unwrap();
241246

242247
// Check request:
243248
let op = get_operation_from_req_bytes(client.get_mock_write());
244249
if let NativeOperation::PsaImportKey(op) = op {
245250
assert_eq!(op.attributes, key_attrs);
246251
assert_eq!(op.key_name, key_name);
247-
assert_eq!(op.data, key_data);
252+
assert_eq!(op.data.expose_secret(), &key_data);
248253
} else {
249254
panic!("Got wrong operation type: {:?}", op);
250255
}
@@ -259,7 +264,7 @@ fn psa_export_public_key_test() {
259264
let key_data = vec![0xa5; 128];
260265
client.set_mock_read(&get_response_bytes_from_result(
261266
NativeResult::PsaExportPublicKey(operations::psa_export_public_key::Result {
262-
data: key_data.clone(),
267+
data: key_data.clone().into(),
263268
}),
264269
));
265270

@@ -292,14 +297,14 @@ fn psa_sign_hash_test() {
292297
let signature = vec![0x33_u8; 128];
293298
client.set_mock_read(&get_response_bytes_from_result(NativeResult::PsaSignHash(
294299
operations::psa_sign_hash::Result {
295-
signature: signature.clone(),
300+
signature: signature.clone().into(),
296301
},
297302
)));
298303

299304
// Check response:
300305
assert_eq!(
301306
client
302-
.psa_sign_hash(key_name.clone(), hash.clone(), sign_algorithm.clone())
307+
.psa_sign_hash(key_name.clone(), &hash, sign_algorithm)
303308
.expect("Failed to sign hash"),
304309
signature
305310
);
@@ -308,7 +313,7 @@ fn psa_sign_hash_test() {
308313
let op = get_operation_from_req_bytes(client.get_mock_write());
309314
if let NativeOperation::PsaSignHash(op) = op {
310315
assert_eq!(op.key_name, key_name);
311-
assert_eq!(op.hash, hash);
316+
assert_eq!(op.hash.to_vec(), hash);
312317
assert_eq!(op.alg, sign_algorithm);
313318
} else {
314319
panic!("Got wrong operation type: {:?}", op);
@@ -329,21 +334,16 @@ fn verify_hash_test() {
329334
));
330335

331336
client
332-
.psa_verify_hash(
333-
key_name.clone(),
334-
hash.clone(),
335-
sign_algorithm.clone(),
336-
signature.clone(),
337-
)
337+
.psa_verify_hash(key_name.clone(), &hash, sign_algorithm, &signature)
338338
.expect("Failed to sign hash");
339339

340340
// Check request:
341341
let op = get_operation_from_req_bytes(client.get_mock_write());
342342
if let NativeOperation::PsaVerifyHash(op) = op {
343343
assert_eq!(op.key_name, key_name);
344-
assert_eq!(op.hash, hash);
344+
assert_eq!(op.hash.to_vec(), hash);
345345
assert_eq!(op.alg, sign_algorithm);
346-
assert_eq!(op.signature, signature);
346+
assert_eq!(op.signature.to_vec(), signature);
347347
} else {
348348
panic!("Got wrong operation type: {:?}", op);
349349
}
@@ -423,7 +423,7 @@ fn auth_value_test() {
423423

424424
let req = get_req_from_bytes(client.get_mock_write());
425425
assert_eq!(
426-
String::from_utf8(req.auth.bytes().to_owned()).unwrap(),
426+
String::from_utf8(req.auth.buffer.expose_secret().to_owned()).unwrap(),
427427
String::from(DEFAULT_APP_NAME)
428428
);
429429
}

src/core/testing/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::auth::AuthenticationData;
77
use crate::error::Result;
88
use mockstream::{FailingMockStream, SyncMockStream};
99
use parsec_interface::requests::ProviderID;
10+
use parsec_interface::secrecy::Secret;
1011
use std::ops::{Deref, DerefMut};
1112
use std::time::Duration;
1213

@@ -66,8 +67,8 @@ impl DerefMut for TestBasicClient {
6667
impl Default for TestBasicClient {
6768
fn default() -> Self {
6869
let mut client = TestBasicClient {
69-
core_client: BasicClient::new(AuthenticationData::AppIdentity(String::from(
70-
DEFAULT_APP_NAME,
70+
core_client: BasicClient::new(AuthenticationData::AppIdentity(Secret::new(
71+
String::from(DEFAULT_APP_NAME),
7172
))),
7273
mock_stream: SyncMockStream::new(),
7374
};

0 commit comments

Comments
 (0)