From 1f9f841d4e5d34c869c40f0bf9a128e75bb34414 Mon Sep 17 00:00:00 2001 From: Samuel Bailey Date: Wed, 1 Jul 2020 18:05:35 +0100 Subject: [PATCH] Added asymmetric encrypt and decrypt to Mbed Crypto provider Signed-off-by: Samuel Bailey --- CONTRIBUTORS.md | 1 + Cargo.lock | 21 +- Cargo.toml | 4 +- e2e_tests/Cargo.toml | 5 +- e2e_tests/src/lib.rs | 145 ++++++++++++- .../normal_tests/asym_encryption.rs | 198 ++++++++++++++++++ .../tests/per_provider/normal_tests/mod.rs | 1 + src/back/backend_handler.rs | 18 ++ .../mbed_provider/asym_encryption.rs | 96 +++++++++ src/providers/mbed_provider/asym_sign.rs | 4 +- src/providers/mbed_provider/key_management.rs | 6 +- src/providers/mbed_provider/mod.rs | 28 ++- src/providers/mod.rs | 25 ++- 13 files changed, 524 insertions(+), 28 deletions(-) create mode 100644 e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs create mode 100644 src/providers/mbed_provider/asym_encryption.rs diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1a36747a..f783948a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -12,3 +12,4 @@ This file aims to acknowledge the specific contributors referred to in the "Cont * Ionut Mihalcea (@ionut-arm) * Hugues de Valon (@hug-dev) * Jesper Brynolf (@Superhepper) +* Samuel Bailey (@sbailey-arm) diff --git a/Cargo.lock b/Cargo.lock index ad266cdc..80125b74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,9 +207,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c1f1d60091c1b73e2b1f4560ab419204b178e625fa945ded7b660becd2bd46" +checksum = "0fde55d2a2bfaa4c9668bbc63f531fbdeee3ffe188f4662511ce2c22b3eedebe" [[package]] name = "cexpr" @@ -433,9 +433,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909" +checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" dependencies = [ "libc", ] @@ -745,9 +745,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "parsec-interface" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db0d49816455026327f6377243442645a590423fa1cca4978cd869f34a383a9" +checksum = "09289310e1dfe55d804e4a3be12c8fe170239e6129ffd8e8b5007078b30c6098" dependencies = [ "arbitrary", "bincode", @@ -968,20 +968,21 @@ dependencies = [ [[package]] name = "psa-crypto" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6fa12271d1af1f3267c176d8c2d28d94cf6fbfe3368fa18ecba1f8a6d083757" +checksum = "640ff8940a8a8f85c4bf8e6f1cd5adb9d26461b598f99c8217d343b27da24cd7" dependencies = [ "log", "psa-crypto-sys", "serde", + "zeroize", ] [[package]] name = "psa-crypto-sys" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d8e707688eb8c0fd95a0441180beacf3e4d2909f9172d6c43d10145edd5d730" +checksum = "8ab13137181ea1aead63adb3f0e44cef57e70804280f2b9b7f47e0f2d0ceb437" dependencies = [ "bindgen", "cc", diff --git a/Cargo.toml b/Cargo.toml index 7addece6..0d818302 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ name = "parsec" path = "src/bin/main.rs" [dependencies] -parsec-interface = "0.17.0" +parsec-interface = "0.18.0" rand = { version = "0.7.2", features = ["small_rng"] } base64 = "0.10.1" uuid = "0.7.4" @@ -40,7 +40,7 @@ derivative = "2.1.1" version = "3.0.0" hex = "0.4.2" picky = "5.0.0" -psa-crypto = { version = "0.2.1" , default-features = false, features = ["with-mbed-crypto"], optional = true } +psa-crypto = { version = "0.2.2" , default-features = false, features = ["with-mbed-crypto"], optional = true } zeroize = { version = "1.1.0", features = ["zeroize_derive"] } [dev-dependencies] diff --git a/e2e_tests/Cargo.toml b/e2e_tests/Cargo.toml index 6d3a379e..f1c54c8d 100644 --- a/e2e_tests/Cargo.toml +++ b/e2e_tests/Cargo.toml @@ -18,10 +18,13 @@ picky-asn1-der = "0.2.2" picky-asn1 = "0.2.1" serde = { version = "1.0", features = ["derive"] } sha2 = "0.8.1" -parsec-client = { git = "https://github.com/parallaxsecond/parsec-client-rust", features = ["testing"] } +parsec-client = { version = "0.6.0", features = ["testing"] } log = "0.4.8" rand = "0.7.3" [dev-dependencies] env_logger = "0.7.1" uuid = "0.7.4" +rsa = "0.3.0" +picky-asn1-x509 = "0.1.0" +base64 = "0.12.3" \ No newline at end of file diff --git a/e2e_tests/src/lib.rs b/e2e_tests/src/lib.rs index c52af50c..ba1c7bb5 100644 --- a/e2e_tests/src/lib.rs +++ b/e2e_tests/src/lib.rs @@ -13,7 +13,7 @@ use parsec_client::auth::AuthenticationData; use parsec_client::core::basic_client::BasicClient; use parsec_client::core::interface::operations::list_providers::ProviderInfo; use parsec_client::core::interface::operations::psa_algorithm::{ - Algorithm, AsymmetricSignature, Hash, + Algorithm, AsymmetricSignature, AsymmetricEncryption, Hash, }; use parsec_client::core::interface::operations::psa_key_attributes::{ Attributes, Lifetime, Policy, Type, UsageFlags, @@ -157,6 +157,60 @@ impl TestClient { ) } + pub fn generate_rsa_encryption_keys_rsapkcs1v15crypt(&mut self, key_name: String) -> Result<()> { + self.generate_key( + key_name, + 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: true, + decrypt: true, + cache: false, + copy: false, + derive: false, + }, + permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), + }, + } + ) + } + + pub fn generate_rsa_encryption_keys_rsaoaep_sha256(&mut self, key_name: String) -> Result<()> { + self.generate_key( + key_name, + 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: true, + decrypt: true, + cache: false, + copy: false, + derive: false, + }, + permitted_algorithms: AsymmetricEncryption::RsaOaep{ + hash_alg: Hash::Sha256, + }.into(), + }, + } + ) + } + /// Imports and creates a key with specific attributes. pub fn import_key( &mut self, @@ -178,7 +232,36 @@ impl TestClient { Ok(()) } - /// Import a 1024 bits RSA public key. + /// Import a 1024 bit RSA key pair + /// The key pair can only be used for encryption and decryption with RSA PKCS 1v15 + pub fn import_rsa_key_pair(&mut self, key_name: String, data: Vec) -> Result<()> { + self.import_key( + key_name, + 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: true, + export: false, + encrypt: true, + decrypt: true, + cache: false, + copy: false, + derive: false, + }, + permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), + }, + }, + data, + ) + } + + /// 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<()> { self.import_key( @@ -287,6 +370,64 @@ impl TestClient { ) } + pub fn asymmetric_encrypt_message_with_rsapkcs1v15( + &mut self, + key_name: String, + plaintext: Vec, + ) -> Result> { + self.asymmetric_encrypt_message( + key_name, + AsymmetricEncryption::RsaPkcs1v15Crypt, + &plaintext, + None, + ) + } + + pub fn asymmetric_decrypt_message_with_rsapkcs1v15( + &mut self, + key_name: String, + ciphertext: Vec, + ) -> Result> { + self.asymmetric_decrypt_message( + key_name, + AsymmetricEncryption::RsaPkcs1v15Crypt, + &ciphertext, + None, + ) + } + + pub fn asymmetric_encrypt_message( + &mut self, + key_name: String, + encryption_alg: AsymmetricEncryption, + plaintext: &[u8], + salt: Option<&[u8]>) -> Result> { + self.basic_client + .psa_asymmetric_encrypt( + key_name, + encryption_alg, + &plaintext, + salt, + ) + .map_err(convert_error) + } + + pub fn asymmetric_decrypt_message( + &mut self, + key_name: String, + encryption_alg: AsymmetricEncryption, + ciphertext: &[u8], + salt: Option<&[u8]>) -> Result> { + self.basic_client + .psa_asymmetric_decrypt( + key_name, + encryption_alg, + &ciphertext, + salt, + ) + .map_err(convert_error) + } + /// Lists the provider available for the Parsec service. pub fn list_providers(&mut self) -> Result> { self.basic_client.list_providers().map_err(convert_error) diff --git a/e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs b/e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs new file mode 100644 index 00000000..57743fd1 --- /dev/null +++ b/e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs @@ -0,0 +1,198 @@ +// Copyright 2020 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use e2e_tests::TestClient; +use parsec_client::core::interface::requests::{ProviderID, ResponseStatus}; +use rsa::{RSAPublicKey, PaddingScheme, PublicKey}; +use rand::rngs::OsRng; + +const PLAINTEXT_MESSAGE: [u8; 32] = [ + 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2, + 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78, +]; + +const PRIVATE_KEY: &str = +"MIICWwIBAAKBgQCd+EKeRmZCKLmg7LasWqpKA9/01linY75ujilf6v/Kb8UP9r/E\ +cO75Pvi2YPnYhBadmVOVxMOqS2zmKm1a9VTegT8dN9Unf2s2KbKrKXupaQTXcrGG\ +SB/BmHeWeiqidEMw7i9ysjHK4KEuacmYmZpvKAnNWMyvQgjGgGNpsNzqawIDAQAB\ +AoGAcHlAxXyOdnCUqpWgAtuS/5v+q06qVJRaFFE3+ElT0oj+ID2pkG5wWBqT7xbh\ +DV4O1CtFLg+o2OlXIhH3RpoC0D0x3qfvDpY5nJUUhP/w7mtGOwvB08xhXBN2M9fk\ +PNqGdrzisvxTry3rp9qDduZlv1rTCsx8+ww3iI4Q0coD4fECQQD4KAMgIS7Vu+Vm\ +zQmJfVfzYCVdr4X3Z/JOEexb3eu9p1Qj904sLu9Ds5NO7atT+qtDYVxgH5kQIrKk\ +mFNAx3NdAkEAovZ+DaorhkDiL/gFVzwoShyc1A6AWkH791sDlns2ETZ1WwE/ccYu\ +uJill/5XA9RKw6whUDzzNTsv7bFkCruAZwJARP5y6ALxz5DfFfbZuPU1d7/6g5Ki\ +b4fh8VzAV0ZbHa6hESLYBCbEdRE/WolvwfiGl0RBd6QxXTAYdPS46ODLLQJARrz4\ +urXDbuN7S5c9ukBCvOjuqp4g2Q0LcrPvOsMBFTeueXJxN9HvNfIM741X+DGOwqFV\ +VJ8gc1rd0y/NXVtGwQJAc2w23nTmZ/olcMVRia1+AFsELcCnD+JqaJ2AEF1Ng6Ix\ +V/X2l32v6t3B57sw/8ce3LCheEdqLHlSOpQiaD7Qfw=="; + +#[allow(dead_code)] +const PUBLIC_KEY: &str = +"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCd+EKeRmZCKLmg7LasWqpKA9/0\ +1linY75ujilf6v/Kb8UP9r/EcO75Pvi2YPnYhBadmVOVxMOqS2zmKm1a9VTegT8d\ +N9Unf2s2KbKrKXupaQTXcrGGSB/BmHeWeiqidEMw7i9ysjHK4KEuacmYmZpvKAnN\ +WMyvQgjGgGNpsNzqawIDAQAB"; + +const ENCRYPTED_MESSAGE: &str = +"ebr0Q/lPf+905a66RjABlZJ8Xl9ZpTHrwVAHd1+sKOT0G4uCUd+q2mpKGljODiMn5gvMj8aMjTOZUROBmrZQpCnB8GCqpGtEOjJtpJy5AdfMTK+QZVvTnvEia1NTjYIoRNCSfFXTQP/ZsAfq2ViiymqwYXM270pHxS3TvBdQH9A="; + +const ORIGINAL_MESSAGE: &str = "This is a test!"; + +#[test] +fn simple_asym_encrypt_rsa_pkcs() { + let key_name = String::from("asym_encrypt_and_decrypt_rsa_pkcs"); + let mut client = TestClient::new(); + + if client.provider() != Some(ProviderID::MbedCrypto) { + // Not supported by current provider + return; + } + + client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap(); + let _ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15( + key_name.clone(), + PLAINTEXT_MESSAGE.to_vec(), + ).unwrap(); +} + +#[test] +fn asym_encrypt_no_key() { + let key_name = String::from("asym_encrypt_no_key"); + let mut client = TestClient::new(); + + if client.provider() != Some(ProviderID::MbedCrypto) { + // Not supported by current provider + return; + } + + let status = client. + asymmetric_encrypt_message_with_rsapkcs1v15( + key_name, + PLAINTEXT_MESSAGE.to_vec(), + ) + .expect_err("Key should not exist."); + assert_eq!(status, ResponseStatus::PsaErrorDoesNotExist); +} + +#[test] +fn asym_decrypt_no_key() { + let key_name = String::from("asym_decrypt_no_key"); + let mut client = TestClient::new(); + + if client.provider() != Some(ProviderID::MbedCrypto) { + // Not supported by current provider + return; + } + + let status = client. + asymmetric_decrypt_message_with_rsapkcs1v15( + key_name, + PLAINTEXT_MESSAGE.to_vec(), + ) + .expect_err("Key should not exist."); + assert_eq!(status, ResponseStatus::PsaErrorDoesNotExist); +} + +#[test] +fn asym_encrypt_wrong_algorithm() { + let key_name = String::from("asym_encrypt_wrong_algorithm"); + let mut client = TestClient::new(); + + if client.provider() != Some(ProviderID::MbedCrypto) { + // Not supported by current provider + return; + } + + let _key_id = client.generate_rsa_encryption_keys_rsaoaep_sha256(key_name.clone()).unwrap(); + let status = client.asymmetric_encrypt_message_with_rsapkcs1v15( + key_name.clone(), + PLAINTEXT_MESSAGE.to_vec(), + ).unwrap_err(); + assert_eq!(status, ResponseStatus::PsaErrorNotPermitted); +} + +#[test] +fn asym_encrypt_and_decrypt_rsa_pkcs() { + let key_name = String::from("asym_encrypt_and_decrypt_rsa_pkcs"); + let mut client = TestClient::new(); + + if client.provider() != Some(ProviderID::MbedCrypto) { + // Not supported by current provider + return; + } + + client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap(); + let ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15( + key_name.clone(), + PLAINTEXT_MESSAGE.to_vec(), + ).unwrap(); + let plaintext = client.asymmetric_decrypt_message_with_rsapkcs1v15( + key_name, + ciphertext, + ).unwrap(); + assert_eq!(PLAINTEXT_MESSAGE.to_vec(), plaintext); +} + +#[test] +fn asym_encrypt_decrypt_rsa_pkcs_different_keys() { + let key_name_1 = String::from("asym_encrypt_and_decrypt_rsa_pkcs_different_keys_1"); + let key_name_2 = String::from("asym_encrypt_and_decrypt_rsa_pkcs_different_keys_2"); + let mut client = TestClient::new(); + + if client.provider() != Some(ProviderID::MbedCrypto) { + // Not supported by current provider + return; + } + + client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name_1.clone()).unwrap(); + client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name_2.clone()).unwrap(); + let ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15( + key_name_1.clone(), + PLAINTEXT_MESSAGE.to_vec(), + ).unwrap(); + let _res = client.asymmetric_decrypt_message_with_rsapkcs1v15( + key_name_2.clone(), + ciphertext, + ).unwrap_err(); +} + +#[test] +fn asym_encrypt_verify_decrypt_with_rsa_crate() { + let key_name = String::from("asym_encrypt_verify_decrypt_with_rsa_crate"); + let mut client = TestClient::new(); + + if client.provider() != Some(ProviderID::MbedCrypto) { + // Not supported by current provider + return; + } + + client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap(); + let pub_key = client.export_public_key(key_name.clone()).unwrap(); + + let rsa_pub_key = RSAPublicKey::from_pkcs1(&pub_key).unwrap(); + let ciphertext = rsa_pub_key.encrypt(&mut OsRng, PaddingScheme::new_pkcs1v15_encrypt(), &PLAINTEXT_MESSAGE).unwrap(); + + let plaintext = client.asymmetric_decrypt_message_with_rsapkcs1v15( + key_name.clone(), + ciphertext, + ).unwrap(); + + assert_eq!(&PLAINTEXT_MESSAGE[..], &plaintext[..]); + +} + +/// Uses key pair generated online to decrypt a message that has been pre-encrypted +#[test] +fn asym_verify_decrypt_with_internet() { + let key_name = String::from("asym_derify_decrypt_with_pick"); + let mut client = TestClient::new(); + + if client.provider() != Some(ProviderID::MbedCrypto) { + // Not supported by current provider + return; + } + + client.import_rsa_key_pair(key_name.clone(), base64::decode(PRIVATE_KEY).unwrap()).unwrap(); + let encrypt_bytes = base64::decode(ENCRYPTED_MESSAGE).unwrap(); + let plaintext_bytes = client.asymmetric_decrypt_message_with_rsapkcs1v15(key_name, encrypt_bytes).unwrap(); + assert_eq!(ORIGINAL_MESSAGE.as_bytes(), plaintext_bytes.as_slice()); +} \ No newline at end of file diff --git a/e2e_tests/tests/per_provider/normal_tests/mod.rs b/e2e_tests/tests/per_provider/normal_tests/mod.rs index beb4dee4..e8b3f954 100644 --- a/e2e_tests/tests/per_provider/normal_tests/mod.rs +++ b/e2e_tests/tests/per_provider/normal_tests/mod.rs @@ -8,3 +8,4 @@ mod export_public_key; mod import_key; mod key_attributes; mod ping; +mod asym_encryption; diff --git a/src/back/backend_handler.rs b/src/back/backend_handler.rs index f62582cd..b8a07547 100644 --- a/src/back/backend_handler.rs +++ b/src/back/backend_handler.rs @@ -159,6 +159,24 @@ impl BackEndHandler { trace!("psa_verify_hash egress"); self.result_to_response(NativeResult::PsaVerifyHash(result), header) } + NativeOperation::PsaAsymmetricEncrypt(op_asymmetric_encrypt) => { + let app_name = + unwrap_or_else_return!(app_name.ok_or(ResponseStatus::NotAuthenticated)); + let result = unwrap_or_else_return!(self + .provider + .psa_asymmetric_encrypt(app_name, op_asymmetric_encrypt)); + trace!("psa_asymmetric_encrypt_egress"); + self.result_to_response(NativeResult::PsaAsymmetricEncrypt(result), header) + } + NativeOperation::PsaAsymmetricDecrypt(op_asymmetric_decrypt) => { + let app_name = + unwrap_or_else_return!(app_name.ok_or(ResponseStatus::NotAuthenticated)); + let result = unwrap_or_else_return!(self + .provider + .psa_asymmetric_decrypt(app_name, op_asymmetric_decrypt)); + trace!("psa_asymmetric_encrypt_egress"); + self.result_to_response(NativeResult::PsaAsymmetricDecrypt(result), header) + } } } } diff --git a/src/providers/mbed_provider/asym_encryption.rs b/src/providers/mbed_provider/asym_encryption.rs new file mode 100644 index 00000000..21440d12 --- /dev/null +++ b/src/providers/mbed_provider/asym_encryption.rs @@ -0,0 +1,96 @@ +// Copyright 2020 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use super::{key_management, MbedProvider}; +use crate::authenticators::ApplicationName; +use crate::key_info_managers::KeyTriple; +use log::info; +use parsec_interface::operations::{psa_asymmetric_decrypt, psa_asymmetric_encrypt}; +use parsec_interface::requests::{ProviderID, ResponseStatus, Result}; +use psa_crypto::operations::asym_encryption; +use psa_crypto::types::key; +use zeroize::Zeroize; + +impl MbedProvider { + pub(super) fn psa_asymmetric_encrypt_internal( + &self, + app_name: ApplicationName, + op: psa_asymmetric_encrypt::Operation, + ) -> Result { + info!("Mbed Provider - Asym Encrypt"); + let key_name = op.key_name.clone(); + + let key_triple = KeyTriple::new(app_name, ProviderID::MbedCrypto, key_name); + let store_handle = self.key_info_store.read().expect("Key store lock poisoned"); + let key_id = key_management::get_key_id(&key_triple, &*store_handle)?; + let _guard = self + .key_handle_mutex + .lock() + .expect("Grabbing key handle mutex failed"); + let id = key::Id::from_persistent_key_id(key_id); + let key_attributes = key::Attributes::from_key_id(id)?; + + op.validate(key_attributes)?; + let salt_buff = op.salt.as_ref().map(|salt| salt.as_slice()); + let alg = op.alg; + let buffer_size = key_attributes.asymmetric_encrypt_output_size(alg)?; + let mut ciphertext = vec![0u8; buffer_size]; + + match asym_encryption::encrypt(id, alg, &op.plaintext, salt_buff, &mut ciphertext) { + Ok(output_size) => { + ciphertext.resize(output_size, 0); + Ok(psa_asymmetric_encrypt::Result { + ciphertext: ciphertext.into(), + }) + } + Err(error) => { + let error = ResponseStatus::from(error); + format_error!("Encrypt status: ", error); + Err(error) + } + } + } + + pub(super) fn psa_asymmetric_decrypt_internal( + &self, + app_name: ApplicationName, + op: psa_asymmetric_decrypt::Operation, + ) -> Result { + info!("Mbed Provider - Asym Decrypt"); + + let key_triple = KeyTriple::new(app_name, ProviderID::MbedCrypto, op.key_name.clone()); + let store_handle = self.key_info_store.read().expect("Key store lock poisoned"); + let key_id = key_management::get_key_id(&key_triple, &*store_handle)?; + + let _guard = self + .key_handle_mutex + .lock() + .expect("Grabbing key handle mutex failed"); + + let id = key::Id::from_persistent_key_id(key_id); + let key_attributes = key::Attributes::from_key_id(id)?; + dbg!("Validating params"); + op.validate(key_attributes)?; + dbg!("Params valid"); + let salt_buff = match &op.salt { + Some(salt) => Some(salt.as_slice()), + None => None, + }; + let buffer_size = key_attributes.asymmetric_decrypt_output_size(op.alg)?; + let mut plaintext = vec![0u8; buffer_size]; + + match asym_encryption::decrypt(id, op.alg, &op.ciphertext, salt_buff, &mut plaintext) { + Ok(output_size) => { + plaintext.resize(output_size, 0); + Ok(psa_asymmetric_decrypt::Result { + plaintext: plaintext.into(), + }) + } + Err(error) => { + plaintext.zeroize(); + let error = ResponseStatus::from(error); + format_error!("Decrypt status: ", error); + Err(error) + } + } + } +} diff --git a/src/providers/mbed_provider/asym_sign.rs b/src/providers/mbed_provider/asym_sign.rs index ef60c7fa..86f5926a 100644 --- a/src/providers/mbed_provider/asym_sign.rs +++ b/src/providers/mbed_provider/asym_sign.rs @@ -42,7 +42,7 @@ impl MbedProvider { } Err(error) => { let error = ResponseStatus::from(error); - format_error!("Sign status: {}", error); + format_error!("Sign status: ", error); Err(error) } } @@ -72,7 +72,7 @@ impl MbedProvider { Ok(()) => Ok(psa_verify_hash::Result {}), Err(error) => { let error = ResponseStatus::from(error); - format_error!("Verify status: {}", error); + format_error!("Verify status: ", error); Err(error) } } diff --git a/src/providers/mbed_provider/key_management.rs b/src/providers/mbed_provider/key_management.rs index d87dfacc..e88dca73 100644 --- a/src/providers/mbed_provider/key_management.rs +++ b/src/providers/mbed_provider/key_management.rs @@ -125,7 +125,7 @@ impl MbedProvider { Err(error) => { remove_key_id(&key_triple, &mut *store_handle)?; let error = ResponseStatus::from(error); - format_error!("Generate key status: {}", error); + format_error!("Generate key status: ", error); Err(error) } } @@ -169,7 +169,7 @@ impl MbedProvider { Err(error) => { remove_key_id(&key_triple, &mut *store_handle)?; let error = ResponseStatus::from(error); - format_error!("Import key status: {}", error); + format_error!("Import key status: ", error); Err(error) } } @@ -240,7 +240,7 @@ impl MbedProvider { } Err(error) => { let error = ResponseStatus::from(error); - format_error!("Destroy key status: {}", error); + format_error!("Destroy key status: ", error); Err(error) } } diff --git a/src/providers/mbed_provider/mod.rs b/src/providers/mbed_provider/mod.rs index 41a555d8..374da84c 100644 --- a/src/providers/mbed_provider/mod.rs +++ b/src/providers/mbed_provider/mod.rs @@ -7,8 +7,8 @@ use derivative::Derivative; use log::{error, trace}; use parsec_interface::operations::list_providers::ProviderInfo; use parsec_interface::operations::{ - psa_destroy_key, psa_export_public_key, psa_generate_key, psa_import_key, psa_sign_hash, - psa_verify_hash, + 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::requests::{Opcode, ProviderID, ResponseStatus, Result}; use psa_crypto::types::{key, status}; @@ -20,6 +20,7 @@ use std::sync::{ }; use uuid::Uuid; +mod asym_encryption; mod asym_sign; #[allow(dead_code)] mod key_management; @@ -104,10 +105,7 @@ impl MbedProvider { } Err(status::Error::DoesNotExist) => to_remove.push(key_triple.clone()), Err(e) => { - format_error!( - "Error {} when opening a persistent Mbed Crypto key.", - e - ); + format_error!("Failed to open persistent Mbed Crypto key", e); return None; } }; @@ -198,6 +196,24 @@ impl Provide for MbedProvider { trace!("psa_verify_hash ingress"); self.psa_verify_hash_internal(app_name, op) } + + fn psa_asymmetric_encrypt( + &self, + app_name: ApplicationName, + op: psa_asymmetric_encrypt::Operation, + ) -> Result { + trace!("psa_asymmetric_encrypt ingress"); + self.psa_asymmetric_encrypt_internal(app_name, op) + } + + fn psa_asymmetric_decrypt( + &self, + app_name: ApplicationName, + op: psa_asymmetric_decrypt::Operation, + ) -> Result { + trace!("psa_asymmetric_decrypt ingress"); + self.psa_asymmetric_decrypt_internal(app_name, op) + } } #[derive(Default, Derivative)] diff --git a/src/providers/mod.rs b/src/providers/mod.rs index 43dca64b..62f1633f 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -75,8 +75,9 @@ impl ProviderConfig { use crate::authenticators::ApplicationName; use parsec_interface::operations::{ - list_opcodes, list_providers, ping, psa_destroy_key, psa_export_public_key, psa_generate_key, - psa_import_key, psa_sign_hash, psa_verify_hash, + list_opcodes, list_providers, ping, 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::requests::{ResponseStatus, Result}; @@ -176,4 +177,24 @@ pub trait Provide { trace!("psa_verify_hash ingress"); Err(ResponseStatus::PsaErrorNotSupported) } + + /// Execute an AsymmetricEncrypt operation. + fn psa_asymmetric_encrypt( + &self, + _app_name: ApplicationName, + _op: psa_asymmetric_encrypt::Operation, + ) -> Result { + trace!("psa_asymmetric_encrypt ingress"); + Err(ResponseStatus::PsaErrorNotSupported) + } + + /// Execute an AsymmetricDecrypt operation. + fn psa_asymmetric_decrypt( + &self, + _app_name: ApplicationName, + _op: psa_asymmetric_decrypt::Operation, + ) -> Result { + trace!("psa_asymmetric_decrypt ingress"); + Err(ResponseStatus::PsaErrorNotSupported) + } }