From 897ab4c92d0b21928807b606eb537450d7f63565 Mon Sep 17 00:00:00 2001 From: Sam Davis Date: Fri, 10 Sep 2021 16:57:42 +0100 Subject: [PATCH] Added the CanDoCrypto operation as well as fixing some of the other test scripts Added the internal CanDoCrypto as a new capability_discovery file in the pkcs11 provider and made corresponding changes to the relevent files. Also added the end to end tests for CanDoCrypto and fixed the other tests that were still using the old syntax for the usage flags. Signed-off-by: Sam Davis --- Cargo.toml | 2 +- e2e_tests/Cargo.toml | 2 +- e2e_tests/src/lib.rs | 288 +++++--------- e2e_tests/tests/all_providers/config/mod.rs | 16 +- e2e_tests/tests/all_providers/normal.rs | 23 +- .../normal_tests/asym_encryption.rs | 30 +- .../normal_tests/asym_sign_verify.rs | 104 +---- .../normal_tests/capability_discovery.rs | 371 ++++++++++++++++++ .../normal_tests/create_destroy_key.rs | 15 +- .../per_provider/normal_tests/export_key.rs | 133 ++----- .../normal_tests/export_public_key.rs | 30 +- .../per_provider/normal_tests/import_key.rs | 64 +-- .../normal_tests/key_attributes.rs | 76 +--- .../tests/per_provider/normal_tests/mod.rs | 1 + src/back/backend_handler.rs | 8 + src/providers/mod.rs | 20 +- src/providers/pkcs11/capability_discovery.rs | 123 ++++++ src/providers/pkcs11/mod.rs | 19 +- 18 files changed, 729 insertions(+), 596 deletions(-) create mode 100644 e2e_tests/tests/per_provider/normal_tests/capability_discovery.rs create mode 100644 src/providers/pkcs11/capability_discovery.rs diff --git a/Cargo.toml b/Cargo.toml index 63b5107f..32e75975 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ name = "parsec" path = "src/bin/main.rs" [dependencies] -parsec-interface = "0.25.0" +parsec-interface = { git = "https://github.com/Kakemone/parsec-interface-rs", branch = "CanDoCrypto_patch" } rand = { version = "0.8.3", features = ["small_rng"], optional = true } base64 = "0.13.0" uuid = "0.8.2" diff --git a/e2e_tests/Cargo.toml b/e2e_tests/Cargo.toml index 48becc4f..27667c46 100644 --- a/e2e_tests/Cargo.toml +++ b/e2e_tests/Cargo.toml @@ -11,7 +11,7 @@ publish = false [dependencies] serde = { version = "1.0.123", features = ["derive"] } -parsec-client = { git = "https://github.com/parallaxsecond/parsec-client-rust.git", rev = "e7c8989aed83343d2d86896f811fbe49f7d0edfc", features = ["testing", "spiffe-auth"] } +parsec-client = { git = "https://github.com/Kakemone/parsec-client-rust", branch = "CanDoCrypto_patch", features = ["testing", "spiffe-auth"] } log = "0.4.14" # Compatible version with crate rsa rand = "0.7.3" diff --git a/e2e_tests/src/lib.rs b/e2e_tests/src/lib.rs index 5171acae..68aafc3f 100644 --- a/e2e_tests/src/lib.rs +++ b/e2e_tests/src/lib.rs @@ -12,6 +12,7 @@ pub use parsec_client::error; use log::error; use parsec_client::auth::Authentication; use parsec_client::core::basic_client::BasicClient; +use parsec_client::core::interface::operations::can_do_crypto::CheckType; use parsec_client::core::interface::operations::list_authenticators::AuthenticatorInfo; use parsec_client::core::interface::operations::list_keys::KeyInfo; use parsec_client::core::interface::operations::list_providers::ProviderInfo; @@ -98,7 +99,7 @@ impl TestClient { /// Creates a key with specific attributes. pub fn generate_key(&mut self, key_name: String, attributes: Attributes) -> Result<()> { self.basic_client - .psa_generate_key(key_name.clone(), attributes) + .psa_generate_key(&key_name.clone(), attributes) .map_err(convert_error)?; let provider = self.provider(); @@ -124,6 +125,12 @@ impl TestClient { /// Generate a 1024 bits RSA key pair. /// The key can only be used for signing/verifying with the RSA PKCS 1v15 signing algorithm with SHA-256 and exporting its public part. pub fn generate_rsa_sign_key(&mut self, key_name: String) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags + .set_sign_hash() + .set_verify_hash() + .set_sign_message() + .set_verify_message(); self.generate_key( key_name, Attributes { @@ -131,18 +138,7 @@ impl TestClient { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: true, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -154,6 +150,12 @@ impl TestClient { } pub fn generate_long_rsa_sign_key(&mut self, key_name: String) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags + .set_sign_hash() + .set_verify_hash() + .set_sign_message() + .set_verify_message(); self.generate_key( key_name, Attributes { @@ -161,18 +163,7 @@ impl TestClient { key_type: Type::RsaKeyPair, bits: 2048, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: true, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -187,6 +178,8 @@ impl TestClient { &mut self, key_name: String, ) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt().set_decrypt(); self.generate_key( key_name, Attributes { @@ -194,18 +187,7 @@ impl TestClient { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: true, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), }, }, @@ -213,6 +195,8 @@ impl TestClient { } pub fn generate_aes_keys_ccm(&mut self, key_name: String) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt().set_decrypt(); self.generate_key( key_name, Attributes { @@ -220,18 +204,7 @@ impl TestClient { key_type: Type::Aes, bits: 192, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: true, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Aead::AeadWithDefaultLengthTag( AeadWithDefaultLengthTag::Ccm, ) @@ -242,6 +215,8 @@ impl TestClient { } pub fn generate_rsa_encryption_keys_rsaoaep_sha256(&mut self, key_name: String) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt().set_decrypt(); self.generate_key( key_name, Attributes { @@ -249,18 +224,7 @@ impl TestClient { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: true, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricEncryption::RsaOaep { hash_alg: Hash::Sha256, } @@ -272,6 +236,8 @@ impl TestClient { #[allow(deprecated)] pub fn generate_rsa_encryption_keys_rsaoaep_sha1(&mut self, key_name: String) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt().set_decrypt(); self.generate_key( key_name, Attributes { @@ -279,18 +245,7 @@ impl TestClient { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: true, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricEncryption::RsaOaep { hash_alg: Hash::Sha1, } @@ -304,6 +259,11 @@ impl TestClient { &mut self, key_name: String, ) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags + .set_sign_hash() + .set_verify_hash() + .set_sign_message(); self.generate_key( key_name, Attributes { @@ -313,18 +273,7 @@ impl TestClient { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: true, - sign_message: true, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricSignature::DeterministicEcdsa { hash_alg: Hash::Sha256.into(), } @@ -335,6 +284,12 @@ impl TestClient { } pub fn generate_ecc_key_pair_secpr1_ecdsa_sha256(&mut self, key_name: String) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags + .set_sign_hash() + .set_verify_hash() + .set_sign_message() + .set_verify_message(); self.generate_key( key_name, Attributes { @@ -344,18 +299,7 @@ impl TestClient { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: true, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), } @@ -368,6 +312,8 @@ impl TestClient { /// Generate ECC key pair with secp R1 curve family. /// The key can only be used for key agreement with Ecdh algorithm. pub fn generate_ecc_pair_secp_r1_key(&mut self, key_name: String) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_derive(); let attributes = Attributes { key_type: Type::EccKeyPair { curve_family: EccFamily::SecpR1, @@ -375,10 +321,7 @@ impl TestClient { bits: 256, lifetime: Lifetime::Volatile, policy: Policy { - usage_flags: UsageFlags { - derive: true, - ..Default::default() - }, + usage_flags, permitted_algorithms: KeyAgreement::Raw(RawKeyAgreement::Ecdh).into(), }, }; @@ -393,7 +336,7 @@ impl TestClient { data: Vec, ) -> Result<()> { self.basic_client - .psa_import_key(key_name.clone(), &data, attributes) + .psa_import_key(&key_name.clone(), &data, attributes) .map_err(convert_error)?; let provider = self.provider(); @@ -413,6 +356,8 @@ impl TestClient { key_name: String, data: Vec, ) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt().set_decrypt(); self.import_key( key_name, Attributes { @@ -420,18 +365,7 @@ impl TestClient { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: true, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), }, }, @@ -444,6 +378,8 @@ impl TestClient { key_name: String, data: Vec, ) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt().set_decrypt().set_verify_message(); self.import_key( key_name, Attributes { @@ -451,18 +387,7 @@ impl TestClient { key_type: Type::RsaPublicKey, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: true, - export: false, - encrypt: true, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), }, }, @@ -473,6 +398,8 @@ impl TestClient { /// Import a 1024 bit RSA public key. /// The key can only be used for verifying with the RSA PKCS 1v15 signing algorithm with SHA-256. pub fn import_rsa_public_key(&mut self, key_name: String, data: Vec) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_hash().set_verify_message(); self.import_key( key_name, Attributes { @@ -480,18 +407,7 @@ impl TestClient { key_type: Type::RsaPublicKey, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: true, - sign_message: false, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -506,6 +422,8 @@ impl TestClient { /// Import an AES key. /// The key can only be used for AEAD encryption and decryption with the CCM algorithm pub fn import_aes_key(&mut self, key_name: String, data: Vec) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt().set_decrypt(); self.import_key( key_name, Attributes { @@ -513,18 +431,7 @@ impl TestClient { key_type: Type::Aes, bits: 0, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: true, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Aead::AeadWithDefaultLengthTag( AeadWithDefaultLengthTag::Ccm, ) @@ -538,6 +445,8 @@ impl TestClient { /// Import ECC key pair with secp R1 curve family. /// The key can only be used for key agreement with Ecdh algorithm. pub fn import_ecc_pair_secp_r1_key(&mut self, key_name: String, data: Vec) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_derive(); let attributes = Attributes { key_type: Type::EccKeyPair { curve_family: EccFamily::SecpR1, @@ -545,10 +454,7 @@ impl TestClient { bits: 256, lifetime: Lifetime::Volatile, policy: Policy { - usage_flags: UsageFlags { - derive: true, - ..Default::default() - }, + usage_flags, permitted_algorithms: KeyAgreement::Raw(RawKeyAgreement::Ecdh).into(), }, }; @@ -562,6 +468,8 @@ impl TestClient { key_name: String, data: Vec, ) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_derive(); let attributes = Attributes { key_type: Type::EccKeyPair { curve_family: EccFamily::BrainpoolPR1, @@ -569,10 +477,7 @@ impl TestClient { bits: 0, lifetime: Lifetime::Volatile, policy: Policy { - usage_flags: UsageFlags { - derive: true, - ..Default::default() - }, + usage_flags, permitted_algorithms: KeyAgreement::Raw(RawKeyAgreement::Ecdh).into(), }, }; @@ -586,6 +491,8 @@ impl TestClient { key_name: String, data: Vec, ) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_hash().set_verify_message(); self.import_key( key_name, Attributes { @@ -595,18 +502,7 @@ impl TestClient { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: true, - sign_message: false, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), } @@ -622,6 +518,12 @@ impl TestClient { key_name: String, data: Vec, ) -> Result<()> { + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags + .set_sign_hash() + .set_sign_message() + .set_verify_hash() + .set_verify_message(); self.import_key( key_name, Attributes { @@ -631,18 +533,7 @@ impl TestClient { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: true, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), } @@ -656,21 +547,21 @@ impl TestClient { /// Exports a key pub fn export_key(&mut self, key_name: String) -> Result> { self.basic_client - .psa_export_key(key_name) + .psa_export_key(&key_name) .map_err(convert_error) } /// Exports a public key. pub fn export_public_key(&mut self, key_name: String) -> Result> { self.basic_client - .psa_export_public_key(key_name) + .psa_export_public_key(&key_name) .map_err(convert_error) } /// Destroys a key. pub fn destroy_key(&mut self, key_name: String) -> Result<()> { self.basic_client - .psa_destroy_key(key_name.clone()) + .psa_destroy_key(&key_name.clone()) .map_err(convert_error)?; let provider = self.provider(); @@ -691,7 +582,7 @@ impl TestClient { hash: Vec, ) -> Result> { self.basic_client - .psa_sign_hash(key_name, &hash, alg) + .psa_sign_hash(&key_name, &hash, alg) .map_err(convert_error) } @@ -726,7 +617,7 @@ impl TestClient { signature: Vec, ) -> Result<()> { self.basic_client - .psa_verify_hash(key_name, &hash, alg, &signature) + .psa_verify_hash(&key_name, &hash, alg, &signature) .map_err(convert_error) } @@ -772,7 +663,7 @@ impl TestClient { msg: Vec, ) -> Result> { self.basic_client - .psa_sign_message(key_name, &msg, alg) + .psa_sign_message(&key_name, &msg, alg) .map_err(convert_error) } @@ -800,7 +691,7 @@ impl TestClient { signature: Vec, ) -> Result<()> { self.basic_client - .psa_verify_message(key_name, &msg, alg, &signature) + .psa_verify_message(&key_name, &msg, alg, &signature) .map_err(convert_error) } @@ -921,7 +812,7 @@ impl TestClient { salt: Option<&[u8]>, ) -> Result> { self.basic_client - .psa_asymmetric_encrypt(key_name, encryption_alg, &plaintext, salt) + .psa_asymmetric_encrypt(&key_name, encryption_alg, &plaintext, salt) .map_err(convert_error) } @@ -933,7 +824,7 @@ impl TestClient { salt: Option<&[u8]>, ) -> Result> { self.basic_client - .psa_asymmetric_decrypt(key_name, encryption_alg, &ciphertext, salt) + .psa_asymmetric_decrypt(&key_name, encryption_alg, &ciphertext, salt) .map_err(convert_error) } @@ -946,7 +837,7 @@ impl TestClient { plaintext: &[u8], ) -> Result> { self.basic_client - .psa_aead_encrypt(key_name, encryption_alg, nonce, additional_data, plaintext) + .psa_aead_encrypt(&key_name, encryption_alg, nonce, additional_data, plaintext) .map_err(convert_error) } @@ -959,7 +850,7 @@ impl TestClient { ciphertext: &[u8], ) -> Result> { self.basic_client - .psa_aead_decrypt(key_name, encryption_alg, nonce, additional_data, ciphertext) + .psa_aead_decrypt(&key_name, encryption_alg, nonce, additional_data, ciphertext) .map_err(convert_error) } @@ -982,7 +873,7 @@ impl TestClient { peer_key: &[u8], ) -> Result> { self.basic_client - .psa_raw_key_agreement(alg, private_key, peer_key) + .psa_raw_key_agreement(alg, &private_key, peer_key) .map_err(convert_error) } @@ -1018,7 +909,7 @@ impl TestClient { /// Delete a client. pub fn delete_client(&mut self, client: String) -> Result<()> { self.basic_client - .delete_client(client) + .delete_client(&client) .map_err(convert_error) } @@ -1026,6 +917,13 @@ impl TestClient { pub fn ping(&mut self) -> Result<(u8, u8)> { self.basic_client.ping().map_err(convert_error) } + + ///Executes the CanDoCrypto operation. + pub fn can_do_crypto(&self, check_type: CheckType, attributes: Attributes) -> Result<()> { + self.basic_client + .can_do_crypto(check_type, attributes) + .map_err(convert_error) + } } impl Default for TestClient { diff --git a/e2e_tests/tests/all_providers/config/mod.rs b/e2e_tests/tests/all_providers/config/mod.rs index e78fb448..970667af 100644 --- a/e2e_tests/tests/all_providers/config/mod.rs +++ b/e2e_tests/tests/all_providers/config/mod.rs @@ -216,6 +216,8 @@ fn allow_export() { reload_service(); let mut client = TestClient::new(); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash().set_verify_hash().set_sign_message().set_verify_message().set_export(); assert_eq!( client .generate_key( @@ -225,19 +227,7 @@ fn allow_export() { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: true, - sign_message: true, - verify_message: true, - // Should not be allowed by configuration - export: true, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), diff --git a/e2e_tests/tests/all_providers/normal.rs b/e2e_tests/tests/all_providers/normal.rs index ddb3d232..2bfdc635 100644 --- a/e2e_tests/tests/all_providers/normal.rs +++ b/e2e_tests/tests/all_providers/normal.rs @@ -68,20 +68,21 @@ fn list_authenticators() { #[test] fn list_opcodes() { let mut client = TestClient::new(); - let mut crypto_providers_hsm = HashSet::new(); + let mut crypto_providers_tpm = HashSet::new(); let mut core_provider_opcodes = HashSet::new(); let mut crypto_providers_cal = HashSet::new(); - let _ = crypto_providers_hsm.insert(Opcode::PsaGenerateKey); - let _ = crypto_providers_hsm.insert(Opcode::PsaDestroyKey); - let _ = crypto_providers_hsm.insert(Opcode::PsaSignHash); - let _ = crypto_providers_hsm.insert(Opcode::PsaVerifyHash); - let _ = crypto_providers_hsm.insert(Opcode::PsaImportKey); - let _ = crypto_providers_hsm.insert(Opcode::PsaExportPublicKey); - let _ = crypto_providers_hsm.insert(Opcode::PsaAsymmetricDecrypt); - let _ = crypto_providers_hsm.insert(Opcode::PsaAsymmetricEncrypt); - - let crypto_providers_tpm = crypto_providers_hsm.clone(); + let _ = crypto_providers_tpm.insert(Opcode::PsaGenerateKey); + let _ = crypto_providers_tpm.insert(Opcode::PsaDestroyKey); + let _ = crypto_providers_tpm.insert(Opcode::PsaSignHash); + let _ = crypto_providers_tpm.insert(Opcode::PsaVerifyHash); + let _ = crypto_providers_tpm.insert(Opcode::PsaImportKey); + let _ = crypto_providers_tpm.insert(Opcode::PsaExportPublicKey); + let _ = crypto_providers_tpm.insert(Opcode::PsaAsymmetricDecrypt); + let _ = crypto_providers_tpm.insert(Opcode::PsaAsymmetricEncrypt); + + let mut crypto_providers_hsm = crypto_providers_tpm.clone(); + let _ = crypto_providers_hsm.insert(Opcode::CanDoCrypto); let mut crypto_providers_mbed_crypto = crypto_providers_tpm.clone(); let _ = crypto_providers_mbed_crypto.insert(Opcode::PsaHashCompute); diff --git a/e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs b/e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs index d25851b3..f5803ad4 100644 --- a/e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs +++ b/e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs @@ -371,23 +371,14 @@ fn asym_encrypt_not_permitted() { return; } + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_decrypt(); let attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), }, }; @@ -409,23 +400,14 @@ fn asym_decrypt_not_permitted() { return; } + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt(); let attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: true, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), }, }; diff --git a/e2e_tests/tests/per_provider/normal_tests/asym_sign_verify.rs b/e2e_tests/tests/per_provider/normal_tests/asym_sign_verify.rs index e4ae1bc8..bccd55cd 100644 --- a/e2e_tests/tests/per_provider/normal_tests/asym_sign_verify.rs +++ b/e2e_tests/tests/per_provider/normal_tests/asym_sign_verify.rs @@ -236,23 +236,14 @@ fn sign_hash_not_permitted() -> Result<()> { hasher.update(b"Bob wrote this message."); let hash = hasher.finalize().to_vec(); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_message().set_verify_hash().set_verify_message(); let attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: true, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -286,6 +277,8 @@ fn sign_hash_not_permitted_ecc() -> Result<()> { hasher.update(b"Bob wrote this message."); let hash = hasher.finalize().to_vec(); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_message().set_verify_hash().set_verify_message(); let attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { @@ -293,18 +286,7 @@ fn sign_hash_not_permitted_ecc() -> Result<()> { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: true, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), @@ -438,23 +420,14 @@ fn verify_hash_not_permitted_rsa() -> Result<()> { hasher.update(b"Bob wrote this message."); let hash = hasher.finalize().to_vec(); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_message().set_sign_hash().set_verify_message(); let attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: false, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -491,6 +464,8 @@ fn verify_hash_not_permitted_ecc() -> Result<()> { hasher.update(b"Bob wrote this message."); let hash = hasher.finalize().to_vec(); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_message().set_sign_hash().set_verify_message(); let attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { @@ -498,18 +473,7 @@ fn verify_hash_not_permitted_ecc() -> Result<()> { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: false, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), @@ -859,6 +823,7 @@ fn sign_message_not_permitted() { let msg = b"Bob wrote this message."; + let usage_flags: UsageFlags = Default::default(); client .generate_key( key_name.clone(), @@ -869,18 +834,7 @@ fn sign_message_not_permitted() { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), } @@ -910,6 +864,8 @@ fn verify_message_not_permitted() { let msg = b"Bob wrote this message."; + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_message(); client .generate_key( key_name.clone(), @@ -920,18 +876,7 @@ fn verify_message_not_permitted() { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: true, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), } @@ -957,6 +902,8 @@ fn verify_message_not_permitted() { fn wildcard_hash_not_supported() { let key_name = String::from("sign_verify_ecc"); let mut client = TestClient::new(); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash().set_verify_hash(); assert_eq!( client @@ -967,18 +914,7 @@ fn wildcard_hash_not_supported() { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: true, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: SignHash::Any, diff --git a/e2e_tests/tests/per_provider/normal_tests/capability_discovery.rs b/e2e_tests/tests/per_provider/normal_tests/capability_discovery.rs new file mode 100644 index 00000000..31f4b3e7 --- /dev/null +++ b/e2e_tests/tests/per_provider/normal_tests/capability_discovery.rs @@ -0,0 +1,371 @@ +// Copyright 2021 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use e2e_tests::TestClient; +use parsec_client::core::interface::operations::psa_algorithm::*; +use parsec_client::core::interface::requests::{Opcode, ResponseStatus}; +use parsec_client::core::interface::operations::psa_key_attributes::*; +use parsec_client::core::interface::operations::can_do_crypto::CheckType; + +#[test] +fn derive_check() { + let mut client = TestClient::new(); + if !client.is_operation_supported(Opcode::CanDoCrypto) { + return + } + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_derive(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 1024, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::None, + }, + }; + + let status = client.can_do_crypto(CheckType::Derive, attributes); + + assert_eq!(Err(ResponseStatus::PsaErrorNotSupported), status) +} + +#[test] +fn key_size_check() { + let mut client = TestClient::new(); + if !client.is_operation_supported(Opcode::CanDoCrypto) { + return + } + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 8, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Err(ResponseStatus::PsaErrorNotSupported), status); + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Ok(()), status); + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 1024, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Err(ResponseStatus::PsaErrorNotSupported), status) +} + +#[test] +fn use_check() { + let mut client = TestClient::new(); + if !client.is_operation_supported(Opcode::CanDoCrypto) { + return + } + + let usage_flags: UsageFlags = Default::default(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::None, + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Err(ResponseStatus::PsaErrorNotSupported), status); + + let usage_flags: UsageFlags = Default::default(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Err(ResponseStatus::PsaErrorNotSupported), status); + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Ok(()), status); + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_message(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Ok(()), status); + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_hash(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Ok(()), status); + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_message(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Ok(()), status); + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_decrypt(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Ok(()), status); + + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }), + }, + }; + + let status = client.can_do_crypto(CheckType::Use, attributes); + + assert_eq!(Ok(()), status) +} + +#[test] +fn generate_check() { + let mut client = TestClient::new(); + if !client.is_operation_supported(Opcode::CanDoCrypto) { + return + } + + let usage_flags: UsageFlags = Default::default(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaKeyPair, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature( + AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }, + ), + }, + }; + + let status = client.can_do_crypto(CheckType::Generate, attributes); + + assert_eq!(Ok(()), status); + + let usage_flags: UsageFlags = Default::default(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::EccKeyPair {curve_family: EccFamily::SecpR1}, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature( + AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }, + ), + }, + }; + + let status = client.can_do_crypto(CheckType::Generate, attributes); + + assert_eq!(Ok(()), status); + + let usage_flags: UsageFlags = Default::default(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature( + AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }, + ), + }, + }; + + let status = client.can_do_crypto(CheckType::Generate, attributes); + + assert_eq!(Err(ResponseStatus::PsaErrorNotSupported), status) +} + +#[test] +fn import_check() { + let mut client = TestClient::new(); + if !client.is_operation_supported(Opcode::CanDoCrypto) { + return + } + + let usage_flags: UsageFlags = Default::default(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaPublicKey, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature( + AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }, + ), + }, + }; + + let status = client.can_do_crypto(CheckType::Import, attributes); + + assert_eq!(Ok(()), status); + + let usage_flags: UsageFlags = Default::default(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::EccPublicKey {curve_family: EccFamily::SecpR1}, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature( + AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }, + ), + }, + }; + + let status = client.can_do_crypto(CheckType::Import, attributes); + + assert_eq!(Ok(()), status); + + let usage_flags: UsageFlags = Default::default(); + let attributes = Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaKeyPair, + bits: 256, + policy: Policy { + usage_flags, + permitted_algorithms: Algorithm::AsymmetricSignature( + AsymmetricSignature::Ecdsa { + hash_alg: Hash::Sha256.into(), + }, + ), + }, + }; + + let status = client.can_do_crypto(CheckType::Import, attributes); + + assert_eq!(Err(ResponseStatus::PsaErrorNotSupported), status) +} \ No newline at end of file diff --git a/e2e_tests/tests/per_provider/normal_tests/create_destroy_key.rs b/e2e_tests/tests/per_provider/normal_tests/create_destroy_key.rs index 8114801c..1ae17d5c 100644 --- a/e2e_tests/tests/per_provider/normal_tests/create_destroy_key.rs +++ b/e2e_tests/tests/per_provider/normal_tests/create_destroy_key.rs @@ -198,6 +198,8 @@ fn try_generate_asymmetric_public_key() { let mut client = TestClient::new(); let key_name = String::from("try_generate_asymmetric_public_key"); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash().set_sign_message().set_verify_hash().set_verify_message(); let err = client .generate_key( key_name, @@ -206,18 +208,7 @@ fn try_generate_asymmetric_public_key() { key_type: Type::RsaPublicKey, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: true, - sign_message: true, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), diff --git a/e2e_tests/tests/per_provider/normal_tests/export_key.rs b/e2e_tests/tests/per_provider/normal_tests/export_key.rs index c56cec9e..d2790ff9 100644 --- a/e2e_tests/tests/per_provider/normal_tests/export_key.rs +++ b/e2e_tests/tests/per_provider/normal_tests/export_key.rs @@ -44,24 +44,15 @@ fn export_key() -> Result<()> { return Ok(()); } + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_export(); let key_name = String::from("export_key"); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: true, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -129,6 +120,8 @@ fn import_and_export_ecc_public_key_by_export_key_fn() -> Result<()> { } let key_name = String::from("import_and_export_ecc_public_key_by_export_key_fn"); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_export().set_verify_message().set_verify_hash(); client.import_key( key_name.clone(), Attributes { @@ -138,18 +131,7 @@ fn import_and_export_ecc_public_key_by_export_key_fn() -> Result<()> { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: true, - sign_message: false, - verify_message: true, - export: true, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), } @@ -174,23 +156,14 @@ fn check_rsa_export_format() -> Result<()> { } let key_name = String::from("check_public_rsa_export_format"); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_export(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: true, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -218,24 +191,15 @@ fn check_export_rsa_possible() -> Result<()> { } let key_name = String::from("check_export_rsa_possible"); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_export(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: true, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -261,24 +225,14 @@ fn check_export_rsa_not_possible() { } let key_name = String::from("check_export_rsa_not_possible"); + let usage_flags: UsageFlags = Default::default(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -305,6 +259,7 @@ fn check_export_ecc_not_possible() { } let key_name = String::from("check_export_ecc_not_possible"); + let usage_flags: UsageFlags = Default::default(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, @@ -313,18 +268,7 @@ fn check_export_ecc_not_possible() { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), @@ -349,6 +293,8 @@ fn export_ecc_private_key() { } let key_name = String::from("export_ecc_private_key"); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_export(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { @@ -356,18 +302,7 @@ fn export_ecc_private_key() { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: true, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), @@ -391,6 +326,8 @@ fn export_ecc_private_key_not_possible() { } let key_name = String::from("export_ecc_private_key_not_possible"); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_export(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { @@ -398,18 +335,7 @@ fn export_ecc_private_key_not_possible() { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: true, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), @@ -434,6 +360,8 @@ fn export_rsa_private_key_matches_import() { } let key_name = String::from("export_rsa_private_key_matches_import"); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_encrypt().set_decrypt().set_export(); let decoded_key = base64::decode(PRIVATE_KEY).unwrap(); client @@ -444,18 +372,7 @@ fn export_rsa_private_key_matches_import() { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: true, - encrypt: true, - decrypt: true, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), }, }, diff --git a/e2e_tests/tests/per_provider/normal_tests/export_public_key.rs b/e2e_tests/tests/per_provider/normal_tests/export_public_key.rs index 6bcf2e94..28efb9b5 100644 --- a/e2e_tests/tests/per_provider/normal_tests/export_public_key.rs +++ b/e2e_tests/tests/per_provider/normal_tests/export_public_key.rs @@ -134,23 +134,14 @@ fn check_export_rsa_public_possible() -> Result<()> { if !client.is_operation_supported(Opcode::PsaExportPublicKey) { return Ok(()); } + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -175,6 +166,8 @@ fn check_export_ecc_public_possible() -> Result<()> { if !client.is_operation_supported(Opcode::PsaExportPublicKey) { return Ok(()); } + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { @@ -182,18 +175,7 @@ fn check_export_ecc_public_possible() -> Result<()> { }, bits: 256, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), diff --git a/e2e_tests/tests/per_provider/normal_tests/import_key.rs b/e2e_tests/tests/per_provider/normal_tests/import_key.rs index 8f0989a2..8fc12b5f 100644 --- a/e2e_tests/tests/per_provider/normal_tests/import_key.rs +++ b/e2e_tests/tests/per_provider/normal_tests/import_key.rs @@ -227,24 +227,14 @@ fn check_format_import2() -> Result<()> { modulus: IntegerAsn1::from_bytes_be_unsigned(example_modulus_1024()), public_exponent: IntegerAsn1::from_bytes_be_unsigned(vec![0x01, 0x00, 0x01]), }; - + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_hash().set_verify_message(); let attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaPublicKey, bits: 0, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: true, - sign_message: false, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -277,24 +267,14 @@ fn check_format_import3() -> Result<()> { modulus: IntegerAsn1::from_bytes_be_unsigned(vec![0xDE; 1024]), public_exponent: IntegerAsn1::from_bytes_be_unsigned(vec![0x01, 0x00, 0x01]), }; - + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_hash().set_verify_message(); let attributes = Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaPublicKey, bits: 1023, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: true, - sign_message: false, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -329,25 +309,15 @@ fn failed_imported_key_should_be_removed() -> Result<()> { modulus: IntegerAsn1::from_bytes_be_unsigned(example_modulus_1024()), public_exponent: IntegerAsn1::from_bytes_be_unsigned(vec![0x01, 0x00, 0x01]), }; - + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_hash().set_verify_message(); let attributes = Attributes { lifetime: Lifetime::Persistent, // Not supported key_type: Type::Aes, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: true, - sign_message: false, - verify_message: true, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), @@ -370,7 +340,8 @@ fn failed_imported_key_should_be_removed() -> Result<()> { fn import_key_pair() { let mut client = TestClient::new(); let key_name = String::from("failed_imported_key_should_be_removed"); - + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash().set_sign_message().set_verify_hash().set_verify_message(); client .import_key( key_name, @@ -379,18 +350,7 @@ fn import_key_pair() { key_type: Type::RsaKeyPair, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - export: false, - copy: false, - cache: false, - encrypt: false, - decrypt: false, - sign_message: true, - sign_hash: true, - verify_message: true, - verify_hash: true, - derive: false, - }, + usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), diff --git a/e2e_tests/tests/per_provider/normal_tests/key_attributes.rs b/e2e_tests/tests/per_provider/normal_tests/key_attributes.rs index 8a6927a6..761c3bfd 100644 --- a/e2e_tests/tests/per_provider/normal_tests/key_attributes.rs +++ b/e2e_tests/tests/per_provider/normal_tests/key_attributes.rs @@ -29,23 +29,14 @@ fn wrong_type() { Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), }); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: permitted_algorithm, }, }; @@ -76,24 +67,14 @@ fn wrong_usage_flags() { Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), }); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_hash(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - // Forbid signing - sign_hash: false, - verify_hash: true, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: permitted_algorithm, }, }; @@ -113,24 +94,14 @@ fn wrong_usage_flags() { let permitted_algorithm = Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_verify_hash(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type, bits: 256, policy: Policy { - usage_flags: UsageFlags { - // Forbid signing - sign_hash: false, - verify_hash: true, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: permitted_algorithm, }, }; @@ -165,23 +136,14 @@ fn wrong_permitted_algorithm() { Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }); + let mut usage_flags: UsageFlags = Default::default(); + let _ = usage_flags.set_sign_hash(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: true, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: permitted_algorithm, }, }; @@ -213,23 +175,13 @@ fn no_usage_flag_set() { Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha256.into(), }); + let usage_flags: UsageFlags = Default::default(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type, bits: 1024, policy: Policy { - usage_flags: UsageFlags { - sign_hash: false, - verify_hash: false, - sign_message: false, - verify_message: false, - export: false, - encrypt: false, - decrypt: false, - cache: false, - copy: false, - derive: false, - }, + usage_flags, permitted_algorithms: permitted_algorithm, }, }; diff --git a/e2e_tests/tests/per_provider/normal_tests/mod.rs b/e2e_tests/tests/per_provider/normal_tests/mod.rs index ac995299..d3b72c40 100644 --- a/e2e_tests/tests/per_provider/normal_tests/mod.rs +++ b/e2e_tests/tests/per_provider/normal_tests/mod.rs @@ -14,3 +14,4 @@ mod import_key; mod key_agreement; mod key_attributes; mod ping; +mod capability_discovery; diff --git a/src/back/backend_handler.rs b/src/back/backend_handler.rs index ef5317d3..3b7c5663 100644 --- a/src/back/backend_handler.rs +++ b/src/back/backend_handler.rs @@ -278,6 +278,14 @@ impl BackEndHandler { trace!("psa_verify_message egress"); self.result_to_response(NativeResult::PsaVerifyMessage(result), header) } + NativeOperation::CanDoCrypto(op_can_do_crypto) => { + let app = unwrap_or_else_return!(app.ok_or(ResponseStatus::NotAuthenticated)); + let result = unwrap_or_else_return!(self + .provider + .can_do_crypto(app.into(), op_can_do_crypto)); + trace!("can_do_crypto egress"); + self.result_to_response(NativeResult::CanDoCrypto(result), header) + } } } } diff --git a/src/providers/mod.rs b/src/providers/mod.rs index 0b9afeb1..80c3bc8b 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -31,11 +31,11 @@ pub mod trusted_service; use crate::authenticators::ApplicationName; use parsec_interface::operations::{ - delete_client, list_authenticators, list_clients, list_keys, list_opcodes, list_providers, - ping, psa_aead_decrypt, psa_aead_encrypt, psa_asymmetric_decrypt, psa_asymmetric_encrypt, - psa_destroy_key, psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random, - psa_hash_compare, psa_hash_compute, psa_import_key, psa_raw_key_agreement, psa_sign_hash, - psa_sign_message, psa_verify_hash, psa_verify_message, + can_do_crypto, delete_client, list_authenticators, list_clients, list_keys, list_opcodes, + list_providers, ping, psa_aead_decrypt, psa_aead_encrypt, psa_asymmetric_decrypt, + psa_asymmetric_encrypt, psa_destroy_key, psa_export_key, psa_export_public_key, + psa_generate_key, psa_generate_random, psa_hash_compare, psa_hash_compute, psa_import_key, + psa_raw_key_agreement, psa_sign_hash, psa_sign_message, psa_verify_hash, psa_verify_message, }; use parsec_interface::requests::{ResponseStatus, Result}; @@ -296,4 +296,14 @@ pub trait Provide { trace!("psa_verify_message ingress"); Err(ResponseStatus::PsaErrorNotSupported) } + + ///Get the filtered list of supported algorithms. + fn can_do_crypto( + &self, + _app_name: ApplicationName, + _op: can_do_crypto::Operation, + ) -> Result { + trace!("can_do_crypto ingress"); + Err(ResponseStatus::PsaErrorNotSupported) + } } diff --git a/src/providers/pkcs11/capability_discovery.rs b/src/providers/pkcs11/capability_discovery.rs new file mode 100644 index 00000000..fc1bb68c --- /dev/null +++ b/src/providers/pkcs11/capability_discovery.rs @@ -0,0 +1,123 @@ +#![allow(unused, trivial_numeric_casts)] +use super::Provider; +use crate::authenticators::ApplicationName; +use crate::providers::pkcs11::to_response_status; +use cryptoki::types::mechanism::Mechanism; +use cryptoki::types::mechanism::MechanismInfo; +use cryptoki::types::mechanism::MechanismType; +use cryptoki::types::Ulong; +use log::trace; +use parsec_interface::operations::can_do_crypto; +use parsec_interface::operations::can_do_crypto::CheckType; +use parsec_interface::operations::psa_algorithm::Algorithm; +use parsec_interface::operations::psa_key_attributes::Attributes; +use parsec_interface::operations::psa_key_attributes::EccFamily; +use parsec_interface::operations::psa_key_attributes::Type; +use parsec_interface::requests::ResponseStatus::{InvalidEncoding, PsaErrorNotSupported}; +use parsec_interface::requests::Result; +use std::convert::TryFrom; +use std::ops::Deref; + +impl Provider { + pub(super) fn can_do_crypto_internal( + &self, + _app_name: ApplicationName, + op: can_do_crypto::Operation, + ) -> Result { + let attributes = op.attributes; + let check_type = op.check_type; + let supported_ecc_family_sizes = [192, 224, 256, 384, 512]; + match attributes.key_type { + Type::EccKeyPair { + curve_family: EccFamily::SecpR1, + } + | Type::EccPublicKey { + curve_family: EccFamily::SecpR1, + } => { + if !(supported_ecc_family_sizes.contains(&attributes.bits)) { + return Err(PsaErrorNotSupported); + } + } + Type::RsaKeyPair | Type::RsaPublicKey => (), + _ => return Err(PsaErrorNotSupported), + } + if attributes.policy.permitted_algorithms != Algorithm::None { + let supported_mechanisms: Vec = self + .backend + .get_mechanism_list(self.slot_number) + .map_err(to_response_status)?; + let mechanism = Mechanism::try_from(attributes.policy.permitted_algorithms) + .map_err(to_response_status)?; + let mechanism_info: MechanismInfo = self + .backend + .get_mechanism_info(self.slot_number, mechanism.mechanism_type()) + .map_err(to_response_status)?; + if !(supported_mechanisms.contains(&mechanism.mechanism_type())) { + return Err(PsaErrorNotSupported); + } + if std::any::type_name::() == std::any::type_name::() { + if !((attributes.bits as u64) >= (*mechanism_info.min_key_size()).into() + && (attributes.bits as u64) <= (*mechanism_info.max_key_size()).into()) + { + return Err(PsaErrorNotSupported); + } + } else { + if !((*mechanism_info.min_key_size() as u64) <= (attributes.bits as u64) + && (attributes.bits as u64) <= (*mechanism_info.max_key_size() as u64)) + { + return Err(PsaErrorNotSupported); + } + } + } + match check_type { + CheckType::Generate => return Provider::generate_check(attributes), + CheckType::Import => return Provider::import_check(attributes), + CheckType::Use => return Provider::use_check(attributes), + CheckType::Derive => return Provider::derive_check(attributes), + }; + return Ok(can_do_crypto::Result {}); + } + + fn use_check(attributes: Attributes) -> Result<()> { + if attributes.policy.permitted_algorithms == Algorithm::None { + return Err(PsaErrorNotSupported); + } else if !(attributes.policy.usage_flags.decrypt() + || attributes.policy.usage_flags.encrypt() + || attributes.policy.usage_flags.sign_hash() + || attributes.policy.usage_flags.sign_message() + || attributes.policy.usage_flags.verify_hash() + || attributes.policy.usage_flags.verify_message()) + { + return Err(PsaErrorNotSupported); + } + return Ok(()); + } + + fn derive_check(attributes: Attributes) -> Result<()> { + return Err(PsaErrorNotSupported); + } + + fn generate_check(attributes: Attributes) -> Result<()> { + if !(attributes.key_type == Type::RsaKeyPair + || attributes.key_type + == (Type::EccKeyPair { + curve_family: EccFamily::SecpR1, + })) + { + return Err(PsaErrorNotSupported); + } + return Ok(()); + } + + fn import_check(attributes: Attributes) -> Result<()> { + if !(attributes.key_type == Type::RsaPublicKey + || attributes.key_type + == (Type::EccPublicKey { + curve_family: EccFamily::SecpR1, + })) + { + return Err(PsaErrorNotSupported); + } + return Ok(()); + } +} diff --git a/src/providers/pkcs11/mod.rs b/src/providers/pkcs11/mod.rs index 5f6bda02..4321af5b 100644 --- a/src/providers/pkcs11/mod.rs +++ b/src/providers/pkcs11/mod.rs @@ -14,11 +14,11 @@ use cryptoki::types::Flags; use cryptoki::Pkcs11; use derivative::Derivative; use log::{error, info, trace, warn}; -use parsec_interface::operations::{list_clients, list_keys, list_providers::ProviderInfo}; use parsec_interface::operations::{ - psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_destroy_key, psa_export_public_key, - psa_generate_key, psa_import_key, psa_sign_hash, psa_verify_hash, + can_do_crypto, psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_destroy_key, + psa_export_public_key, psa_generate_key, psa_import_key, psa_sign_hash, psa_verify_hash, }; +use parsec_interface::operations::{list_clients, list_keys, list_providers::ProviderInfo}; use parsec_interface::requests::{Opcode, ProviderId, ResponseStatus, Result}; use parsec_interface::secrecy::{ExposeSecret, SecretString}; use std::collections::HashSet; @@ -35,11 +35,12 @@ type LocalIdStore = HashSet; mod asym_encryption; mod asym_sign; +mod capability_discovery; mod key_management; mod key_metadata; mod utils; -const SUPPORTED_OPCODES: [Opcode; 8] = [ +const SUPPORTED_OPCODES: [Opcode; 9] = [ Opcode::PsaGenerateKey, Opcode::PsaDestroyKey, Opcode::PsaSignHash, @@ -48,6 +49,7 @@ const SUPPORTED_OPCODES: [Opcode; 8] = [ Opcode::PsaExportPublicKey, Opcode::PsaAsymmetricDecrypt, Opcode::PsaAsymmetricEncrypt, + Opcode::CanDoCrypto, ]; /// Provider for Public Key Cryptography Standard #11 @@ -337,6 +339,15 @@ impl Provide for Provider { trace!("psa_asymmetric_decrypt ingress"); self.psa_asymmetric_decrypt_internal(app_name, op) } + + fn can_do_crypto( + &self, + app_name: ApplicationName, + op: can_do_crypto::Operation, + ) -> Result { + trace!("can_do_crypto ingress"); + self.can_do_crypto_internal(app_name, op) + } } /// Builder for Pkcs11Provider