Skip to content

Commit 79a3a14

Browse files
committed
Added asymmetric encrypt and decrypt to Mbed Crypto provider
Signed-off-by: Samuel Bailey <[email protected]>
1 parent 6ca8010 commit 79a3a14

File tree

13 files changed

+410
-28
lines changed

13 files changed

+410
-28
lines changed

CONTRIBUTORS.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ This file aims to acknowledge the specific contributors referred to in the "Cont
1212
* Ionut Mihalcea (@ionut-arm)
1313
* Hugues de Valon (@hug-dev)
1414
* Jesper Brynolf (@Superhepper)
15+
* Samuel Bailey (@sbailey-arm)

Cargo.lock

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

Cargo.toml

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

2020
[dependencies]
21-
parsec-interface = "0.17.0"
21+
parsec-interface = { path = "../parsec-interface-rs" }
2222
rand = { version = "0.7.2", features = ["small_rng"] }
2323
base64 = "0.10.1"
2424
uuid = "0.7.4"
@@ -40,7 +40,7 @@ derivative = "2.1.1"
4040
version = "3.0.0"
4141
hex = "0.4.2"
4242
picky = "5.0.0"
43-
psa-crypto = { version = "0.2.1" , default-features = false, features = ["with-mbed-crypto"], optional = true }
43+
psa-crypto = { version = "0.2.2" , default-features = false, features = ["with-mbed-crypto"], optional = true }
4444
zeroize = { version = "1.1.0", features = ["zeroize_derive"] }
4545

4646
[dev-dependencies]

e2e_tests/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ picky-asn1-der = "0.2.2"
1818
picky-asn1 = "0.2.1"
1919
serde = { version = "1.0", features = ["derive"] }
2020
sha2 = "0.8.1"
21-
parsec-client = { git = "https://github.com/parallaxsecond/parsec-client-rust", features = ["testing"] }
21+
parsec-client = { path = "../../parsec-client-rust", features = ["testing"] }
2222
log = "0.4.8"
2323
rand = "0.7.3"
2424

2525
[dev-dependencies]
2626
env_logger = "0.7.1"
2727
uuid = "0.7.4"
28+
rsa = "0.3.0"

e2e_tests/src/lib.rs

+113-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use parsec_client::auth::AuthenticationData;
1313
use parsec_client::core::basic_client::BasicClient;
1414
use parsec_client::core::interface::operations::list_providers::ProviderInfo;
1515
use parsec_client::core::interface::operations::psa_algorithm::{
16-
Algorithm, AsymmetricSignature, Hash,
16+
Algorithm, AsymmetricSignature, AsymmetricEncryption, Hash,
1717
};
1818
use parsec_client::core::interface::operations::psa_key_attributes::{
1919
Attributes, Lifetime, Policy, Type, UsageFlags,
@@ -157,6 +157,60 @@ impl TestClient {
157157
)
158158
}
159159

160+
pub fn generate_rsa_encryption_keys_rsapkcs1v15crypt(&mut self, key_name: String) -> Result<()> {
161+
self.generate_key(
162+
key_name,
163+
Attributes {
164+
lifetime: Lifetime::Persistent,
165+
key_type: Type::RsaKeyPair,
166+
bits: 1024,
167+
policy: Policy {
168+
usage_flags: UsageFlags {
169+
sign_hash: false,
170+
verify_hash: false,
171+
sign_message: false,
172+
verify_message: false,
173+
export: true,
174+
encrypt: true,
175+
decrypt: true,
176+
cache: false,
177+
copy: false,
178+
derive: false,
179+
},
180+
permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(),
181+
},
182+
}
183+
)
184+
}
185+
186+
pub fn generate_rsa_encryption_keys_rsaoaep_sha256(&mut self, key_name: String) -> Result<()> {
187+
self.generate_key(
188+
key_name,
189+
Attributes {
190+
lifetime: Lifetime::Persistent,
191+
key_type: Type::RsaKeyPair,
192+
bits: 1024,
193+
policy: Policy {
194+
usage_flags: UsageFlags {
195+
sign_hash: false,
196+
verify_hash: false,
197+
sign_message: false,
198+
verify_message: false,
199+
export: true,
200+
encrypt: true,
201+
decrypt: true,
202+
cache: false,
203+
copy: false,
204+
derive: false,
205+
},
206+
permitted_algorithms: AsymmetricEncryption::RsaOaep{
207+
hash_alg: Hash::Sha256,
208+
}.into(),
209+
},
210+
}
211+
)
212+
}
213+
160214
/// Imports and creates a key with specific attributes.
161215
pub fn import_key(
162216
&mut self,
@@ -287,6 +341,64 @@ impl TestClient {
287341
)
288342
}
289343

344+
pub fn asymmetric_encrypt_message_with_rsapkcs1v15(
345+
&mut self,
346+
key_name: String,
347+
plaintext: Vec<u8>,
348+
) -> Result<Vec<u8>> {
349+
self.asymmetric_encrypt_message(
350+
key_name,
351+
AsymmetricEncryption::RsaPkcs1v15Crypt,
352+
&plaintext,
353+
None,
354+
)
355+
}
356+
357+
pub fn asymmetric_decrypt_message_with_rsapkcs1v15(
358+
&mut self,
359+
key_name: String,
360+
ciphertext: Vec<u8>,
361+
) -> Result<Vec<u8>> {
362+
self.asymmetric_decrypt_message(
363+
key_name,
364+
AsymmetricEncryption::RsaPkcs1v15Crypt,
365+
&ciphertext,
366+
None,
367+
)
368+
}
369+
370+
pub fn asymmetric_encrypt_message(
371+
&mut self,
372+
key_name: String,
373+
encryption_alg: AsymmetricEncryption,
374+
plaintext: &[u8],
375+
salt: Option<&[u8]>) -> Result<Vec<u8>> {
376+
self.basic_client
377+
.psa_asymmetric_encrypt(
378+
key_name,
379+
encryption_alg,
380+
&plaintext,
381+
salt,
382+
)
383+
.map_err(convert_error)
384+
}
385+
386+
pub fn asymmetric_decrypt_message(
387+
&mut self,
388+
key_name: String,
389+
encryption_alg: AsymmetricEncryption,
390+
ciphertext: &[u8],
391+
salt: Option<&[u8]>) -> Result<Vec<u8>> {
392+
self.basic_client
393+
.psa_asymmetric_decrypt(
394+
key_name,
395+
encryption_alg,
396+
&ciphertext,
397+
salt,
398+
)
399+
.map_err(convert_error)
400+
}
401+
290402
/// Lists the provider available for the Parsec service.
291403
pub fn list_providers(&mut self) -> Result<Vec<ProviderInfo>> {
292404
self.basic_client.list_providers().map_err(convert_error)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright 2020 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use e2e_tests::TestClient;
4+
use parsec_client::core::interface::requests::ResponseStatus;
5+
use rsa::{RSAPublicKey, PaddingScheme, PublicKey};
6+
use rand::rngs::OsRng;
7+
8+
9+
const PLAINTEXT_MESSAGE: [u8; 32] = [
10+
0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
11+
0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
12+
];
13+
14+
#[test]
15+
fn simple_asym_encrypt_rsa_pkcs() {
16+
let key_name = String::from("asym_encrypt_and_decrypt_rsa_pkcs");
17+
let mut client = TestClient::new();
18+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap();
19+
let _ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15(
20+
key_name.clone(),
21+
PLAINTEXT_MESSAGE.to_vec(),
22+
).unwrap();
23+
}
24+
25+
#[test]
26+
fn asym_encrypt_no_key() {
27+
let key_name = String::from("asym_encrypt_no_key");
28+
let mut client = TestClient::new();
29+
let status = client.
30+
asymmetric_encrypt_message_with_rsapkcs1v15(
31+
key_name,
32+
PLAINTEXT_MESSAGE.to_vec(),
33+
)
34+
.expect_err("Key should not exist.");
35+
assert_eq!(status, ResponseStatus::PsaErrorDoesNotExist);
36+
}
37+
38+
#[test]
39+
fn asym_decrypt_no_key() {
40+
let key_name = String::from("asym_decrypt_no_key");
41+
let mut client = TestClient::new();
42+
let status = client.
43+
asymmetric_decrypt_message_with_rsapkcs1v15(
44+
key_name,
45+
PLAINTEXT_MESSAGE.to_vec(),
46+
)
47+
.expect_err("Key should not exist.");
48+
assert_eq!(status, ResponseStatus::PsaErrorDoesNotExist);
49+
}
50+
51+
#[test]
52+
fn asym_encrypt_wrong_algorithm() {
53+
let key_name = String::from("asym_encrypt_wrong_algorithm");
54+
let mut client = TestClient::new();
55+
let _key_id = client.generate_rsa_encryption_keys_rsaoaep_sha256(key_name.clone()).unwrap();
56+
let status = client.asymmetric_encrypt_message_with_rsapkcs1v15(
57+
key_name.clone(),
58+
PLAINTEXT_MESSAGE.to_vec(),
59+
).unwrap_err();
60+
assert_eq!(status, ResponseStatus::PsaErrorNotPermitted);
61+
}
62+
63+
#[test]
64+
fn asym_encrypt_and_decrypt_rsa_pkcs() {
65+
let key_name = String::from("asym_encrypt_and_decrypt_rsa_pkcs");
66+
let mut client = TestClient::new();
67+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap();
68+
let ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15(
69+
key_name.clone(),
70+
PLAINTEXT_MESSAGE.to_vec(),
71+
).unwrap();
72+
let plaintext = client.asymmetric_decrypt_message_with_rsapkcs1v15(
73+
key_name,
74+
ciphertext,
75+
).unwrap();
76+
assert_eq!(PLAINTEXT_MESSAGE.to_vec(), plaintext);
77+
}
78+
79+
#[test]
80+
fn asym_encrypt_decrypt_rsa_pkcs_different_keys() {
81+
let key_name_1 = String::from("asym_encrypt_and_decrypt_rsa_pkcs_different_keys_1");
82+
let key_name_2 = String::from("asym_encrypt_and_decrypt_rsa_pkcs_different_keys_2");
83+
let mut client = TestClient::new();
84+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name_1.clone()).unwrap();
85+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name_2.clone()).unwrap();
86+
let ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15(
87+
key_name_1.clone(),
88+
PLAINTEXT_MESSAGE.to_vec(),
89+
).unwrap();
90+
let _res = client.asymmetric_decrypt_message_with_rsapkcs1v15(
91+
key_name_2.clone(),
92+
ciphertext,
93+
).unwrap_err();
94+
}
95+
96+
#[test]
97+
fn asym_encrypt_verify_decrypt_with_rsa_crate() {
98+
let key_name = String::from("asym_encrypt_verify_decrypt_with_rsa_crate");
99+
let mut client = TestClient::new();
100+
101+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap();
102+
let pub_key = client.export_public_key(key_name.clone()).unwrap();
103+
104+
let rsa_pub_key = RSAPublicKey::from_pkcs1(&pub_key).unwrap();
105+
let ciphertext = rsa_pub_key.encrypt(&mut OsRng, PaddingScheme::new_pkcs1v15_encrypt(), &PLAINTEXT_MESSAGE).unwrap();
106+
107+
let plaintext = client.asymmetric_decrypt_message_with_rsapkcs1v15(
108+
key_name.clone(),
109+
ciphertext,
110+
).unwrap();
111+
112+
assert_eq!(&PLAINTEXT_MESSAGE[..], &plaintext[..]);
113+
114+
}
115+

e2e_tests/tests/per_provider/normal_tests/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ mod export_public_key;
88
mod import_key;
99
mod key_attributes;
1010
mod ping;
11+
mod asym_encryption;

src/back/backend_handler.rs

+18
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ impl BackEndHandler {
159159
trace!("psa_verify_hash egress");
160160
self.result_to_response(NativeResult::PsaVerifyHash(result), header)
161161
}
162+
NativeOperation::PsaAsymmetricEncrypt(op_asymmetric_encrypt) => {
163+
let app_name =
164+
unwrap_or_else_return!(app_name.ok_or(ResponseStatus::NotAuthenticated));
165+
let result = unwrap_or_else_return!(self
166+
.provider
167+
.psa_asymmetric_encrypt(app_name, op_asymmetric_encrypt));
168+
trace!("psa_asymmetric_encrypt_egress");
169+
self.result_to_response(NativeResult::PsaAsymmetricEncrypt(result), header)
170+
}
171+
NativeOperation::PsaAsymmetricDecrypt(op_asymmetric_decrypt) => {
172+
let app_name =
173+
unwrap_or_else_return!(app_name.ok_or(ResponseStatus::NotAuthenticated));
174+
let result = unwrap_or_else_return!(self
175+
.provider
176+
.psa_asymmetric_decrypt(app_name, op_asymmetric_decrypt));
177+
trace!("psa_asymmetric_encrypt_egress");
178+
self.result_to_response(NativeResult::PsaAsymmetricDecrypt(result), header)
179+
}
162180
}
163181
}
164182
}

0 commit comments

Comments
 (0)