Skip to content

Commit

Permalink
Added asymmetric encrypt and decrypt to Mbed Crypto provider
Browse files Browse the repository at this point in the history
Signed-off-by: Samuel Bailey <samuel.bailey@arm.com>
  • Loading branch information
sbailey-arm committed Jul 7, 2020
1 parent 6ca8010 commit 79a3a14
Show file tree
Hide file tree
Showing 13 changed files with 410 additions and 28 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
21 changes: 10 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ name = "parsec"
path = "src/bin/main.rs"

[dependencies]
parsec-interface = "0.17.0"
parsec-interface = { path = "../parsec-interface-rs" }
rand = { version = "0.7.2", features = ["small_rng"] }
base64 = "0.10.1"
uuid = "0.7.4"
Expand All @@ -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]
Expand Down
3 changes: 2 additions & 1 deletion e2e_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ 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 = { path = "../../parsec-client-rust", 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"
114 changes: 113 additions & 1 deletion e2e_tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -287,6 +341,64 @@ 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)
Expand Down
115 changes: 115 additions & 0 deletions e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2020 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
use e2e_tests::TestClient;
use parsec_client::core::interface::requests::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,
];

#[test]
fn simple_asym_encrypt_rsa_pkcs() {
let key_name = String::from("asym_encrypt_and_decrypt_rsa_pkcs");
let mut client = TestClient::new();
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();
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();
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();
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();
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();
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();

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[..]);

}

1 change: 1 addition & 0 deletions e2e_tests/tests/per_provider/normal_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ mod export_public_key;
mod import_key;
mod key_attributes;
mod ping;
mod asym_encryption;
18 changes: 18 additions & 0 deletions src/back/backend_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
}
Expand Down
Loading

0 comments on commit 79a3a14

Please sign in to comment.