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 1b6605b3..1d7e8df9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -213,9 +213,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"
@@ -439,9 +439,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",
 ]
@@ -757,9 +757,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",
@@ -994,20 +994,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 e72ea801..5140f7ea 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"] }
 picky-asn1-x509 = { version = "0.1.0", optional = true }
 
diff --git a/e2e_tests/Cargo.toml b/e2e_tests/Cargo.toml
index e9e07b06..d19b8c21 100644
--- a/e2e_tests/Cargo.toml
+++ b/e2e_tests/Cargo.toml
@@ -25,4 +25,6 @@ rand = "0.7.3"
 [dev-dependencies]
 env_logger = "0.7.1"
 uuid = "0.7.4"
-picky-asn1-x509 = "0.1.0"
\ No newline at end of file
+rsa = "0.3.0"
+picky-asn1-x509 = "0.1.0"
+base64 = "0.12.3"
diff --git a/e2e_tests/src/lib.rs b/e2e_tests/src/lib.rs
index 70924de3..9d07c423 100644
--- a/e2e_tests/src/lib.rs
+++ b/e2e_tests/src/lib.rs
@@ -14,7 +14,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, AsymmetricEncryption, AsymmetricSignature, Hash,
 };
 use parsec_client::core::interface::operations::psa_key_attributes::{
     Attributes, Lifetime, Policy, Type, UsageFlags,
@@ -79,6 +79,12 @@ impl TestClient {
         ProviderID::Core
     }
 
+    pub fn is_operation_supported(&mut self, op: Opcode) -> bool {
+        self.list_opcodes(self.provider().unwrap())
+            .unwrap()
+            .contains(&op)
+    }
+
     /// Manually set the provider to execute the requests.
     pub fn set_provider(&mut self, provider: ProviderID) {
         self.basic_client.set_implicit_provider(provider);
@@ -158,6 +164,64 @@ 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,
@@ -179,7 +243,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<u8>) -> 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<u8>) -> Result<()> {
         self.import_key(
@@ -288,6 +381,56 @@ impl TestClient {
         )
     }
 
+    pub fn asymmetric_encrypt_message_with_rsapkcs1v15(
+        &mut self,
+        key_name: String,
+        plaintext: Vec<u8>,
+    ) -> Result<Vec<u8>> {
+        self.asymmetric_encrypt_message(
+            key_name,
+            AsymmetricEncryption::RsaPkcs1v15Crypt,
+            &plaintext,
+            None,
+        )
+    }
+
+    pub fn asymmetric_decrypt_message_with_rsapkcs1v15(
+        &mut self,
+        key_name: String,
+        ciphertext: Vec<u8>,
+    ) -> Result<Vec<u8>> {
+        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<Vec<u8>> {
+        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<Vec<u8>> {
+        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<Vec<ProviderInfo>> {
         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..cc19429b
--- /dev/null
+++ b/e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs
@@ -0,0 +1,200 @@
+// Copyright 2020 Contributors to the Parsec project.
+// SPDX-License-Identifier: Apache-2.0
+use e2e_tests::TestClient;
+use parsec_client::core::interface::requests::{Opcode, ResponseStatus};
+use rand::rngs::OsRng;
+use rsa::{PaddingScheme, PublicKey, RSAPublicKey};
+
+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.is_operation_supported(Opcode::PsaAsymmetricEncrypt) {
+        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.is_operation_supported(Opcode::PsaAsymmetricEncrypt) {
+        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.is_operation_supported(Opcode::PsaAsymmetricDecrypt) {
+        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.is_operation_supported(Opcode::PsaAsymmetricEncrypt) {
+        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.is_operation_supported(Opcode::PsaAsymmetricEncrypt)
+        || !client.is_operation_supported(Opcode::PsaAsymmetricDecrypt)
+    {
+        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.is_operation_supported(Opcode::PsaAsymmetricEncrypt)
+        || !client.is_operation_supported(Opcode::PsaAsymmetricDecrypt)
+    {
+        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.is_operation_supported(Opcode::PsaAsymmetricDecrypt) {
+        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.is_operation_supported(Opcode::PsaAsymmetricDecrypt) {
+        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());
+}
diff --git a/e2e_tests/tests/per_provider/normal_tests/mod.rs b/e2e_tests/tests/per_provider/normal_tests/mod.rs
index beb4dee4..df4d38e7 100644
--- a/e2e_tests/tests/per_provider/normal_tests/mod.rs
+++ b/e2e_tests/tests/per_provider/normal_tests/mod.rs
@@ -1,5 +1,6 @@
 // Copyright 2019 Contributors to the Parsec project.
 // SPDX-License-Identifier: Apache-2.0
+mod asym_encryption;
 mod asym_sign_verify;
 mod auth;
 mod basic;
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..f1b57084
--- /dev/null
+++ b/src/providers/mbed_provider/asym_encryption.rs
@@ -0,0 +1,88 @@
+// 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 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;
+
+impl MbedProvider {
+    pub(super) fn psa_asymmetric_encrypt_internal(
+        &self,
+        app_name: ApplicationName,
+        op: psa_asymmetric_encrypt::Operation,
+    ) -> Result<psa_asymmetric_encrypt::Result> {
+        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<psa_asymmetric_decrypt::Result> {
+        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)?;
+        op.validate(key_attributes)?;
+        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) => {
+                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..be4b5119 100644
--- a/src/providers/mbed_provider/asym_sign.rs
+++ b/src/providers/mbed_provider/asym_sign.rs
@@ -3,7 +3,6 @@
 use super::{key_management, MbedProvider};
 use crate::authenticators::ApplicationName;
 use crate::key_info_managers::KeyTriple;
-use log::info;
 use parsec_interface::operations::{psa_sign_hash, psa_verify_hash};
 use parsec_interface::requests::{ProviderID, ResponseStatus, Result};
 use psa_crypto::operations::asym_signature;
@@ -15,7 +14,6 @@ impl MbedProvider {
         app_name: ApplicationName,
         op: psa_sign_hash::Operation,
     ) -> Result<psa_sign_hash::Result> {
-        info!("Mbed Provider - Asym Sign");
         let key_name = op.key_name;
         let hash = op.hash;
         let alg = op.alg;
@@ -42,7 +40,7 @@ impl MbedProvider {
             }
             Err(error) => {
                 let error = ResponseStatus::from(error);
-                format_error!("Sign status: {}", error);
+                format_error!("Sign status: ", error);
                 Err(error)
             }
         }
@@ -53,7 +51,6 @@ impl MbedProvider {
         app_name: ApplicationName,
         op: psa_verify_hash::Operation,
     ) -> Result<psa_verify_hash::Result> {
-        info!("Mbed Provider - Asym Verify");
         let key_name = op.key_name;
         let hash = op.hash;
         let alg = op.alg;
@@ -72,7 +69,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..75e1cc2e 100644
--- a/src/providers/mbed_provider/key_management.rs
+++ b/src/providers/mbed_provider/key_management.rs
@@ -5,7 +5,7 @@ use crate::authenticators::ApplicationName;
 use crate::key_info_managers;
 use crate::key_info_managers::{KeyInfo, KeyTriple, ManageKeyInfo};
 use log::error;
-use log::{info, warn};
+use log::warn;
 use parsec_interface::operations::psa_key_attributes::Attributes;
 use parsec_interface::operations::{
     psa_destroy_key, psa_export_public_key, psa_generate_key, psa_import_key,
@@ -97,7 +97,6 @@ impl MbedProvider {
         app_name: ApplicationName,
         op: psa_generate_key::Operation,
     ) -> Result<psa_generate_key::Result> {
-        info!("Mbed Provider - Create Key");
         let key_name = op.key_name;
         let key_attributes = op.attributes;
         let key_triple = KeyTriple::new(app_name, ProviderID::MbedCrypto, key_name);
@@ -125,7 +124,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)
             }
         }
@@ -136,7 +135,6 @@ impl MbedProvider {
         app_name: ApplicationName,
         op: psa_import_key::Operation,
     ) -> Result<psa_import_key::Result> {
-        info!("Mbed Provider - Import Key");
         let key_name = op.key_name;
         let key_attributes = op.attributes;
         let key_data = op.data;
@@ -169,7 +167,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)
             }
         }
@@ -180,7 +178,6 @@ impl MbedProvider {
         app_name: ApplicationName,
         op: psa_export_public_key::Operation,
     ) -> Result<psa_export_public_key::Result> {
-        info!("Mbed Provider - Export Public Key");
         let key_name = op.key_name;
         let key_triple = KeyTriple::new(app_name, ProviderID::MbedCrypto, key_name);
         let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
@@ -209,7 +206,6 @@ impl MbedProvider {
         app_name: ApplicationName,
         op: psa_destroy_key::Operation,
     ) -> Result<psa_destroy_key::Result> {
-        info!("Mbed Provider - Destroy Key");
         let key_name = op.key_name;
         let key_triple = KeyTriple::new(app_name, ProviderID::MbedCrypto, key_name);
         let mut store_handle = self
@@ -240,7 +236,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<psa_asymmetric_encrypt::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<psa_asymmetric_decrypt::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<psa_asymmetric_encrypt::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<psa_asymmetric_decrypt::Result> {
+        trace!("psa_asymmetric_decrypt ingress");
+        Err(ResponseStatus::PsaErrorNotSupported)
+    }
 }
diff --git a/src/providers/pkcs11_provider/asym_sign.rs b/src/providers/pkcs11_provider/asym_sign.rs
index 6a25abeb..37ac6f26 100644
--- a/src/providers/pkcs11_provider/asym_sign.rs
+++ b/src/providers/pkcs11_provider/asym_sign.rs
@@ -25,8 +25,6 @@ impl Pkcs11Provider {
         app_name: ApplicationName,
         op: psa_sign_hash::Operation,
     ) -> Result<psa_sign_hash::Result> {
-        info!("Pkcs11 Provider - Asym Sign");
-
         let key_name = op.key_name;
         let hash = op.hash;
         let alg = op.alg;
@@ -113,8 +111,6 @@ impl Pkcs11Provider {
         app_name: ApplicationName,
         op: psa_verify_hash::Operation,
     ) -> Result<psa_verify_hash::Result> {
-        info!("Pkcs11 Provider - Asym Verify");
-
         let key_name = op.key_name;
         let hash = op.hash;
         let signature = op.signature;
diff --git a/src/providers/pkcs11_provider/key_management.rs b/src/providers/pkcs11_provider/key_management.rs
index 7c7c00e1..f1fc6717 100644
--- a/src/providers/pkcs11_provider/key_management.rs
+++ b/src/providers/pkcs11_provider/key_management.rs
@@ -145,8 +145,6 @@ impl Pkcs11Provider {
         app_name: ApplicationName,
         op: psa_generate_key::Operation,
     ) -> Result<psa_generate_key::Result> {
-        info!("Pkcs11 Provider - Create Key");
-
         if op.attributes.key_type != Type::RsaKeyPair {
             error!("The PKCS11 provider currently only supports creating RSA key pairs.");
             return Err(ResponseStatus::PsaErrorNotSupported);
@@ -248,8 +246,6 @@ impl Pkcs11Provider {
         app_name: ApplicationName,
         op: psa_import_key::Operation,
     ) -> Result<psa_import_key::Result> {
-        info!("Pkcs11 Provider - Import Key");
-
         if op.attributes.key_type != Type::RsaPublicKey {
             error!("The PKCS 11 provider currently only supports importing RSA public key.");
             return Err(ResponseStatus::PsaErrorNotSupported);
@@ -390,8 +386,6 @@ impl Pkcs11Provider {
         app_name: ApplicationName,
         op: psa_export_public_key::Operation,
     ) -> Result<psa_export_public_key::Result> {
-        info!("Pkcs11 Provider - Export Public Key");
-
         let key_name = op.key_name;
         let key_triple = KeyTriple::new(app_name, ProviderID::Pkcs11, key_name);
         let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
@@ -488,8 +482,6 @@ impl Pkcs11Provider {
         app_name: ApplicationName,
         op: psa_destroy_key::Operation,
     ) -> Result<psa_destroy_key::Result> {
-        info!("Pkcs11 Provider - Destroy Key");
-
         let key_name = op.key_name;
         let key_triple = KeyTriple::new(app_name, ProviderID::Pkcs11, key_name);
         let mut store_handle = self