Skip to content

Commit 48d2f90

Browse files
authored
Merge pull request #261 from joechrisellis/add-list-keys
Add list keys
2 parents 1b18d01 + f58a43f commit 48d2f90

File tree

13 files changed

+192
-18
lines changed

13 files changed

+192
-18
lines changed

Cargo.lock

+1-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ name = "parsec"
1818
path = "src/bin/main.rs"
1919

2020
[dependencies]
21-
parsec-interface = "0.20.2"
21+
# Set to the newest interface version before releasing
22+
parsec-interface = { git = "https://github.com/parallaxsecond/parsec-interface-rs.git", rev = "4986c0d6b4610237c85eb799fc469d1658c1a2f0" }
2223
rand = { version = "0.7.3", features = ["small_rng"], optional = true }
2324
base64 = "0.12.3"
2425
uuid = "0.8.1"

e2e_tests/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ publish = false
1414

1515
[dependencies]
1616
serde = { version = "1.0.115", features = ["derive"] }
17-
parsec-client = { version = "0.10.0", features = ["testing"] }
17+
parsec-client = { git = "https://github.com/parallaxsecond/parsec-client-rust", rev = "dbd449a9e736f9f972e5489fb2d67949b93484dc", features = ["testing"] }
1818
log = "0.4.11"
1919
rand = "0.7.3"
2020

e2e_tests/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use log::error;
1313
use parsec_client::auth::AuthenticationData;
1414
use parsec_client::core::basic_client::BasicClient;
1515
use parsec_client::core::interface::operations::list_authenticators::AuthenticatorInfo;
16+
use parsec_client::core::interface::operations::list_keys::KeyInfo;
1617
use parsec_client::core::interface::operations::list_providers::ProviderInfo;
1718
use parsec_client::core::interface::operations::psa_algorithm::{
1819
Aead, AeadWithDefaultLengthTag, Algorithm, AsymmetricEncryption, AsymmetricSignature, Hash,
@@ -904,6 +905,11 @@ impl TestClient {
904905
.map_err(convert_error)
905906
}
906907

908+
/// Lists the keys created.
909+
pub fn list_keys(&mut self) -> Result<Vec<KeyInfo>> {
910+
self.basic_client.list_keys().map_err(convert_error)
911+
}
912+
907913
/// Executes a ping operation.
908914
pub fn ping(&mut self) -> Result<(u8, u8)> {
909915
self.basic_client.ping().map_err(convert_error)

e2e_tests/tests/all_providers/mod.rs

+34
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ fn list_opcodes() {
6565
let _ = core_provider_opcodes.insert(Opcode::ListProviders);
6666
let _ = core_provider_opcodes.insert(Opcode::ListAuthenticators);
6767
let _ = core_provider_opcodes.insert(Opcode::ListOpcodes);
68+
let _ = core_provider_opcodes.insert(Opcode::ListKeys);
6869

6970
assert_eq!(
7071
client
@@ -113,3 +114,36 @@ fn sign_verify_with_provider_discovery() -> Result<()> {
113114
let key_name = String::from("sign_verify_with_provider_discovery");
114115
client.generate_rsa_sign_key(key_name)
115116
}
117+
118+
#[test]
119+
fn list_keys() {
120+
let mut client = TestClient::new();
121+
client.set_auth("list_keys test".to_string());
122+
123+
let keys = client.list_keys().expect("list_keys failed");
124+
125+
assert!(keys.is_empty());
126+
127+
let key1 = String::from("list_keys1");
128+
let key2 = String::from("list_keys2");
129+
let key3 = String::from("list_keys3");
130+
131+
client.set_provider(ProviderID::MbedCrypto);
132+
client.generate_rsa_sign_key(key1.clone()).unwrap();
133+
client.set_provider(ProviderID::Pkcs11);
134+
client.generate_rsa_sign_key(key2.clone()).unwrap();
135+
client.set_provider(ProviderID::Tpm);
136+
client.generate_rsa_sign_key(key3.clone()).unwrap();
137+
138+
let key_names: Vec<String> = client
139+
.list_keys()
140+
.expect("list_keys failed")
141+
.into_iter()
142+
.map(|k| k.name)
143+
.collect();
144+
145+
assert_eq!(key_names.len(), 3);
146+
assert!(key_names.contains(&key1));
147+
assert!(key_names.contains(&key2));
148+
assert!(key_names.contains(&key3));
149+
}

src/authenticators/unix_peer_credentials_authenticator/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl Authenticate for UnixPeerCredentialsAuthenticator {
3535
version_maj: 0,
3636
version_min: 1,
3737
version_rev: 0,
38-
id: AuthType::PeerCredentials,
38+
id: AuthType::UnixPeerCredentials,
3939
})
4040
}
4141

src/back/backend_handler.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use crate::authenticators::ApplicationName;
99
use crate::providers::Provide;
1010
use derivative::Derivative;
11-
use log::trace;
11+
use log::{error, trace};
1212
use parsec_interface::operations::Convert;
1313
use parsec_interface::operations::{NativeOperation, NativeResult};
1414
use parsec_interface::requests::{
@@ -53,12 +53,19 @@ impl BackEndHandler {
5353
/// the request.
5454
///
5555
/// # Errors
56+
/// - if the provider ID can not perform the type of operation, returns
57+
/// `ResponseStatus::PsaErrorNotSupported`
5658
/// - if the provider ID does not match, returns `ResponseStatus::WrongProviderID`
5759
/// - if the content type does not match, returns `ResponseStatus::ContentTypeNotSupported`
5860
/// - if the accept type does not match, returns `ResponseStatus::AcceptTypeNotSupported`
5961
pub fn is_capable(&self, request: &Request) -> Result<()> {
6062
let header = &request.header;
6163

64+
if (self.provider_id == ProviderID::Core) != header.opcode.is_core() {
65+
error!("The request's operation is not compatible with the provider targeted.");
66+
return Err(ResponseStatus::PsaErrorNotSupported);
67+
}
68+
6269
if header.provider != self.provider_id {
6370
Err(ResponseStatus::WrongProviderID)
6471
} else if header.content_type != self.content_type {
@@ -207,6 +214,14 @@ impl BackEndHandler {
207214
trace!("list_authenticators egress");
208215
self.result_to_response(NativeResult::ListAuthenticators(result), header)
209216
}
217+
NativeOperation::ListKeys(op_list_keys) => {
218+
let app_name =
219+
unwrap_or_else_return!(app_name.ok_or(ResponseStatus::NotAuthenticated));
220+
let result =
221+
unwrap_or_else_return!(self.provider.list_keys(app_name, op_list_keys));
222+
trace!("list_keys egress");
223+
self.result_to_response(NativeResult::ListKeys(result), header)
224+
}
210225
NativeOperation::PsaHashCompute(op_hash_compute) => {
211226
let _app_name =
212227
unwrap_or_else_return!(app_name.ok_or(ResponseStatus::NotAuthenticated));

src/key_info_managers/mod.rs

+37
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,40 @@ pub trait ManageKeyInfo {
145145
/// Returns an error as a String if there was a problem accessing the Key Info Manager.
146146
fn exists(&self, key_triple: &KeyTriple) -> Result<bool, String>;
147147
}
148+
149+
/// Returns a Vec of the KeyInfo objects corresponding to the given application name and
150+
/// provider ID.
151+
///
152+
/// # Errors
153+
///
154+
/// Returns an error as a String if there was a problem accessing the Key Info Manager.
155+
pub fn list_keys(
156+
manager: &dyn ManageKeyInfo,
157+
app_name: &ApplicationName,
158+
provider_id: ProviderID,
159+
) -> Result<Vec<parsec_interface::operations::list_keys::KeyInfo>, String> {
160+
use parsec_interface::operations::list_keys::KeyInfo;
161+
162+
let mut keys: Vec<KeyInfo> = Vec::new();
163+
let key_triples = manager.get_all(provider_id)?;
164+
165+
for key_triple in key_triples {
166+
if key_triple.app_name() != app_name {
167+
continue;
168+
}
169+
170+
let key_info = manager.get(key_triple)?;
171+
let key_info = match key_info {
172+
Some(key_info) => key_info,
173+
_ => continue,
174+
};
175+
176+
keys.push(KeyInfo {
177+
provider_id: ProviderID::MbedCrypto,
178+
name: key_triple.key_name().to_string(),
179+
attributes: key_info.attributes,
180+
});
181+
}
182+
183+
Ok(keys)
184+
}

src/providers/core/mod.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
//! aiding clients in discovering the capabilities offered by their underlying
77
//! platform.
88
use super::Provide;
9+
use crate::authenticators::ApplicationName;
910
use derivative::Derivative;
1011
use log::trace;
11-
use parsec_interface::operations::{list_authenticators, list_opcodes, list_providers, ping};
1212
use parsec_interface::operations::{
13-
list_authenticators::AuthenticatorInfo, list_providers::ProviderInfo,
13+
list_authenticators, list_keys, list_opcodes, list_providers, ping,
14+
};
15+
use parsec_interface::operations::{
16+
list_authenticators::AuthenticatorInfo, list_keys::KeyInfo, list_providers::ProviderInfo,
1417
};
1518
use parsec_interface::requests::{Opcode, ProviderID, ResponseStatus, Result};
1619
use std::collections::{HashMap, HashSet};
@@ -20,11 +23,12 @@ use std::sync::Arc;
2023
use uuid::Uuid;
2124
use version::{version, Version};
2225

23-
const SUPPORTED_OPCODES: [Opcode; 4] = [
26+
const SUPPORTED_OPCODES: [Opcode; 5] = [
2427
Opcode::ListProviders,
2528
Opcode::ListOpcodes,
2629
Opcode::Ping,
2730
Opcode::ListAuthenticators,
31+
Opcode::ListKeys,
2832
];
2933

3034
/// Service information provider
@@ -73,6 +77,22 @@ impl Provide for Provider {
7377
})
7478
}
7579

80+
fn list_keys(
81+
&self,
82+
app_name: ApplicationName,
83+
_op: list_keys::Operation,
84+
) -> Result<list_keys::Result> {
85+
trace!("list_keys ingress");
86+
87+
let mut keys: Vec<KeyInfo> = Vec::new();
88+
for provider in &self.prov_list {
89+
let mut result = provider.list_keys(app_name.clone(), _op)?;
90+
keys.append(&mut result.keys);
91+
}
92+
93+
Ok(list_keys::Result { keys })
94+
}
95+
7696
fn ping(&self, _op: ping::Operation) -> Result<ping::Result> {
7797
trace!("ping ingress");
7898
let result = ping::Result {

src/providers/mbed_crypto/mod.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
//! This provider is a software based implementation of PSA Crypto, Mbed Crypto.
66
use super::Provide;
77
use crate::authenticators::ApplicationName;
8-
use crate::key_info_managers::{KeyTriple, ManageKeyInfo};
8+
use crate::key_info_managers::{self, KeyTriple, ManageKeyInfo};
99
use derivative::Derivative;
1010
use log::{error, trace};
11-
use parsec_interface::operations::list_providers::ProviderInfo;
11+
use parsec_interface::operations::{list_keys, list_providers::ProviderInfo};
1212
use parsec_interface::operations::{
1313
psa_aead_decrypt, psa_aead_encrypt, psa_asymmetric_decrypt, psa_asymmetric_encrypt,
1414
psa_destroy_key, psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random,
@@ -19,6 +19,7 @@ use parsec_interface::requests::{Opcode, ProviderID, ResponseStatus, Result};
1919
use psa_crypto::types::{key, status};
2020
use std::collections::HashSet;
2121
use std::io::{Error, ErrorKind};
22+
use std::ops::Deref;
2223
use std::sync::{
2324
atomic::{AtomicU32, Ordering::Relaxed},
2425
Arc, Mutex, RwLock,
@@ -161,6 +162,25 @@ impl Provide for Provider {
161162
}, SUPPORTED_OPCODES.iter().copied().collect()))
162163
}
163164

165+
fn list_keys(
166+
&self,
167+
app_name: ApplicationName,
168+
_op: list_keys::Operation,
169+
) -> Result<list_keys::Result> {
170+
let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
171+
Ok(list_keys::Result {
172+
keys: key_info_managers::list_keys(
173+
store_handle.deref(),
174+
&app_name,
175+
ProviderID::MbedCrypto,
176+
)
177+
.map_err(|e| {
178+
format_error!("Error occurred when fetching key information", e);
179+
ResponseStatus::KeyInfoManagerError
180+
})?,
181+
})
182+
}
183+
164184
fn psa_generate_key(
165185
&self,
166186
app_name: ApplicationName,

src/providers/mod.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ impl ProviderConfig {
9191

9292
use crate::authenticators::ApplicationName;
9393
use parsec_interface::operations::{
94-
list_authenticators, list_opcodes, list_providers, ping, psa_aead_decrypt, psa_aead_encrypt,
95-
psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_destroy_key, psa_export_key,
96-
psa_export_public_key, psa_generate_key, psa_generate_random, psa_hash_compare,
94+
list_authenticators, list_keys, list_opcodes, list_providers, ping, psa_aead_decrypt,
95+
psa_aead_encrypt, psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_destroy_key,
96+
psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random, psa_hash_compare,
9797
psa_hash_compute, psa_import_key, psa_raw_key_agreement, psa_sign_hash, psa_verify_hash,
9898
};
9999
use parsec_interface::requests::{ResponseStatus, Result};
@@ -132,6 +132,16 @@ pub trait Provide {
132132
Err(ResponseStatus::PsaErrorNotSupported)
133133
}
134134

135+
/// Lists all keys belonging to the application.
136+
fn list_keys(
137+
&self,
138+
_app_name: ApplicationName,
139+
_op: list_keys::Operation,
140+
) -> Result<list_keys::Result> {
141+
trace!("list_keys ingress");
142+
Err(ResponseStatus::PsaErrorNotSupported)
143+
}
144+
135145
/// Execute a Ping operation to get the wire protocol version major and minor information.
136146
///
137147
/// # Errors

src/providers/pkcs11/mod.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
//! through the Parsec interface.
77
use super::Provide;
88
use crate::authenticators::ApplicationName;
9-
use crate::key_info_managers::{KeyInfo, KeyTriple, ManageKeyInfo};
9+
use crate::key_info_managers::{self, KeyInfo, KeyTriple, ManageKeyInfo};
1010
use derivative::Derivative;
1111
use log::{error, info, trace, warn};
12-
use parsec_interface::operations::list_providers::ProviderInfo;
12+
use parsec_interface::operations::{list_keys, list_providers::ProviderInfo};
1313
use parsec_interface::operations::{
1414
psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_destroy_key, psa_export_public_key,
1515
psa_generate_key, psa_import_key, psa_sign_hash, psa_verify_hash,
@@ -20,6 +20,7 @@ use pkcs11::types::{CKF_OS_LOCKING_OK, CK_C_INITIALIZE_ARGS, CK_SLOT_ID};
2020
use pkcs11::Ctx;
2121
use std::collections::HashSet;
2222
use std::io::{Error, ErrorKind};
23+
use std::ops::Deref;
2324
use std::str::FromStr;
2425
use std::sync::{Arc, Mutex, RwLock};
2526
use utils::{KeyPairType, ReadWriteSession, Session};
@@ -212,6 +213,21 @@ impl Provide for Provider {
212213
))
213214
}
214215

216+
fn list_keys(
217+
&self,
218+
app_name: ApplicationName,
219+
_op: list_keys::Operation,
220+
) -> Result<list_keys::Result> {
221+
let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
222+
Ok(list_keys::Result {
223+
keys: key_info_managers::list_keys(store_handle.deref(), &app_name, ProviderID::Pkcs11)
224+
.map_err(|e| {
225+
format_error!("Error occurred when fetching key information", e);
226+
ResponseStatus::KeyInfoManagerError
227+
})?,
228+
})
229+
}
230+
215231
fn psa_generate_key(
216232
&self,
217233
app_name: ApplicationName,

0 commit comments

Comments
 (0)