Skip to content

Commit 163bbd6

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

File tree

13 files changed

+450
-27
lines changed

13 files changed

+450
-27
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

+11-10
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 = "0.18.0"
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 = { version = "0.6.0", 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,157 @@
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::{ProviderID, 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+
19+
if client.provider() != Some(ProviderID::MbedCrypto) {
20+
// Not supported by current provider
21+
return;
22+
}
23+
24+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap();
25+
let _ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15(
26+
key_name.clone(),
27+
PLAINTEXT_MESSAGE.to_vec(),
28+
).unwrap();
29+
}
30+
31+
#[test]
32+
fn asym_encrypt_no_key() {
33+
let key_name = String::from("asym_encrypt_no_key");
34+
let mut client = TestClient::new();
35+
36+
if client.provider() != Some(ProviderID::MbedCrypto) {
37+
// Not supported by current provider
38+
return;
39+
}
40+
41+
let status = client.
42+
asymmetric_encrypt_message_with_rsapkcs1v15(
43+
key_name,
44+
PLAINTEXT_MESSAGE.to_vec(),
45+
)
46+
.expect_err("Key should not exist.");
47+
assert_eq!(status, ResponseStatus::PsaErrorDoesNotExist);
48+
}
49+
50+
#[test]
51+
fn asym_decrypt_no_key() {
52+
let key_name = String::from("asym_decrypt_no_key");
53+
let mut client = TestClient::new();
54+
55+
if client.provider() != Some(ProviderID::MbedCrypto) {
56+
// Not supported by current provider
57+
return;
58+
}
59+
60+
let status = client.
61+
asymmetric_decrypt_message_with_rsapkcs1v15(
62+
key_name,
63+
PLAINTEXT_MESSAGE.to_vec(),
64+
)
65+
.expect_err("Key should not exist.");
66+
assert_eq!(status, ResponseStatus::PsaErrorDoesNotExist);
67+
}
68+
69+
#[test]
70+
fn asym_encrypt_wrong_algorithm() {
71+
let key_name = String::from("asym_encrypt_wrong_algorithm");
72+
let mut client = TestClient::new();
73+
74+
if client.provider() != Some(ProviderID::MbedCrypto) {
75+
// Not supported by current provider
76+
return;
77+
}
78+
79+
let _key_id = client.generate_rsa_encryption_keys_rsaoaep_sha256(key_name.clone()).unwrap();
80+
let status = client.asymmetric_encrypt_message_with_rsapkcs1v15(
81+
key_name.clone(),
82+
PLAINTEXT_MESSAGE.to_vec(),
83+
).unwrap_err();
84+
assert_eq!(status, ResponseStatus::PsaErrorNotPermitted);
85+
}
86+
87+
#[test]
88+
fn asym_encrypt_and_decrypt_rsa_pkcs() {
89+
let key_name = String::from("asym_encrypt_and_decrypt_rsa_pkcs");
90+
let mut client = TestClient::new();
91+
92+
if client.provider() != Some(ProviderID::MbedCrypto) {
93+
// Not supported by current provider
94+
return;
95+
}
96+
97+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap();
98+
let ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15(
99+
key_name.clone(),
100+
PLAINTEXT_MESSAGE.to_vec(),
101+
).unwrap();
102+
let plaintext = client.asymmetric_decrypt_message_with_rsapkcs1v15(
103+
key_name,
104+
ciphertext,
105+
).unwrap();
106+
assert_eq!(PLAINTEXT_MESSAGE.to_vec(), plaintext);
107+
}
108+
109+
#[test]
110+
fn asym_encrypt_decrypt_rsa_pkcs_different_keys() {
111+
let key_name_1 = String::from("asym_encrypt_and_decrypt_rsa_pkcs_different_keys_1");
112+
let key_name_2 = String::from("asym_encrypt_and_decrypt_rsa_pkcs_different_keys_2");
113+
let mut client = TestClient::new();
114+
115+
if client.provider() != Some(ProviderID::MbedCrypto) {
116+
// Not supported by current provider
117+
return;
118+
}
119+
120+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name_1.clone()).unwrap();
121+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name_2.clone()).unwrap();
122+
let ciphertext = client.asymmetric_encrypt_message_with_rsapkcs1v15(
123+
key_name_1.clone(),
124+
PLAINTEXT_MESSAGE.to_vec(),
125+
).unwrap();
126+
let _res = client.asymmetric_decrypt_message_with_rsapkcs1v15(
127+
key_name_2.clone(),
128+
ciphertext,
129+
).unwrap_err();
130+
}
131+
132+
#[test]
133+
fn asym_encrypt_verify_decrypt_with_rsa_crate() {
134+
let key_name = String::from("asym_encrypt_verify_decrypt_with_rsa_crate");
135+
let mut client = TestClient::new();
136+
137+
if client.provider() != Some(ProviderID::MbedCrypto) {
138+
// Not supported by current provider
139+
return;
140+
}
141+
142+
143+
client.generate_rsa_encryption_keys_rsapkcs1v15crypt(key_name.clone()).unwrap();
144+
let pub_key = client.export_public_key(key_name.clone()).unwrap();
145+
146+
let rsa_pub_key = RSAPublicKey::from_pkcs1(&pub_key).unwrap();
147+
let ciphertext = rsa_pub_key.encrypt(&mut OsRng, PaddingScheme::new_pkcs1v15_encrypt(), &PLAINTEXT_MESSAGE).unwrap();
148+
149+
let plaintext = client.asymmetric_decrypt_message_with_rsapkcs1v15(
150+
key_name.clone(),
151+
ciphertext,
152+
).unwrap();
153+
154+
assert_eq!(&PLAINTEXT_MESSAGE[..], &plaintext[..]);
155+
156+
}
157+

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;

0 commit comments

Comments
 (0)