Skip to content

Commit 6550709

Browse files
author
Joe Ellis
committed
Add support for psa_generate_random operation for MbedCrypto provider
Signed-off-by: Joe Ellis <joe.ellis@arm.com>
1 parent 30c8162 commit 6550709

File tree

8 files changed

+119
-9
lines changed

8 files changed

+119
-9
lines changed

e2e_tests/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ impl TestClient {
134134
Ok(())
135135
}
136136

137+
/// Generates `nbytes` worth of random bytes.
138+
pub fn generate_bytes(&mut self, nbytes: usize) -> Result<Vec<u8>> {
139+
let random_bytes = self
140+
.basic_client
141+
.psa_generate_random(nbytes)
142+
.map_err(convert_error)?;
143+
144+
Ok(random_bytes)
145+
}
146+
137147
/// Generate a 1024 bits RSA key pair.
138148
/// The key can only be used for signing/verifying with the RSA PKCS 1v15 signing algorithm with SHA-256 and exporting its public part.
139149
pub fn generate_rsa_sign_key(&mut self, key_name: String) -> Result<()> {

e2e_tests/tests/all_providers/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ fn list_opcodes() {
5757
let _ = crypto_providers_mbed_crypto.insert(Opcode::PsaAeadEncrypt);
5858
let _ = crypto_providers_mbed_crypto.insert(Opcode::PsaAeadDecrypt);
5959
let _ = crypto_providers_mbed_crypto.insert(Opcode::PsaExportKey);
60+
let _ = crypto_providers_mbed_crypto.insert(Opcode::PsaGenerateRandom);
6061

6162
let _ = core_provider_opcodes.insert(Opcode::Ping);
6263
let _ = core_provider_opcodes.insert(Opcode::ListProviders);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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::Opcode;
5+
6+
#[test]
7+
fn simple_generate_random() {
8+
let mut client = TestClient::new();
9+
10+
if !client.is_operation_supported(Opcode::PsaGenerateRandom) {
11+
return;
12+
}
13+
14+
// Less than one in ~35 billion chance of collision. Should be good enough for our testing.
15+
const NBYTES: usize = 35;
16+
let random_bytes_a = client.generate_bytes(NBYTES).unwrap();
17+
let random_bytes_b = client.generate_bytes(NBYTES).unwrap();
18+
19+
assert_eq!(random_bytes_a.len(), NBYTES);
20+
assert_eq!(random_bytes_b.len(), NBYTES);
21+
22+
for (a, b) in random_bytes_a.iter().zip(random_bytes_b.iter()) {
23+
if *a != *b {
24+
return;
25+
}
26+
}
27+
28+
panic!(
29+
"Two vectors of {} randomly generated bytes were equal!",
30+
NBYTES
31+
);
32+
}
33+
34+
#[test]
35+
fn generate_zero_bytes() {
36+
let mut client = TestClient::new();
37+
38+
if !client.is_operation_supported(Opcode::PsaGenerateRandom) {
39+
return;
40+
}
41+
42+
const NBYTES: usize = 0;
43+
let random_bytes = client.generate_bytes(NBYTES).unwrap();
44+
45+
assert_eq!(random_bytes, vec![]);
46+
}

e2e_tests/tests/per_provider/normal_tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod basic;
88
mod create_destroy_key;
99
mod export_key;
1010
mod export_public_key;
11+
mod generate_random;
1112
mod hash;
1213
mod import_key;
1314
mod key_agreement;

src/back/backend_handler.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,6 @@ impl BackEndHandler {
223223
trace!("psa_aead_decrypt_egress");
224224
self.result_to_response(NativeResult::PsaHashCompare(result), header)
225225
}
226-
NativeOperation::PsaGenerateRandom(_) => {
227-
panic!("Unsupported in this PR");
228-
}
229226
NativeOperation::PsaRawKeyAgreement(op_raw_key_agreement) => {
230227
let app_name =
231228
unwrap_or_else_return!(app_name.ok_or(ResponseStatus::NotAuthenticated));
@@ -235,6 +232,12 @@ impl BackEndHandler {
235232
trace!("psa_raw_key_agreement_egress");
236233
self.result_to_response(NativeResult::PsaRawKeyAgreement(result), header)
237234
}
235+
NativeOperation::PsaGenerateRandom(op_generate_random) => {
236+
let result =
237+
unwrap_or_else_return!(self.provider.psa_generate_random(op_generate_random));
238+
trace!("psa_generate_random_egress");
239+
self.result_to_response(NativeResult::PsaGenerateRandom(result), header)
240+
}
238241
}
239242
}
240243
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use super::MbedCryptoProvider;
2+
use parsec_interface::operations::psa_generate_random;
3+
use parsec_interface::requests::{ResponseStatus, Result};
4+
use psa_crypto::operations::other::generate_random;
5+
6+
impl MbedCryptoProvider {
7+
pub(super) fn psa_generate_random_internal(
8+
&self,
9+
op: psa_generate_random::Operation,
10+
) -> Result<psa_generate_random::Result> {
11+
let buffer_size = op.size;
12+
if buffer_size > crate::utils::GlobalConfig::buffer_size_limit() {
13+
let error = ResponseStatus::ResponseTooLarge;
14+
format_error!("Generate random status", error);
15+
return Err(error);
16+
}
17+
18+
let mut buffer = vec![0u8; buffer_size];
19+
match generate_random(&mut buffer) {
20+
Ok(_) => Ok(psa_generate_random::Result {
21+
random_bytes: buffer.into(),
22+
}),
23+
Err(error) => {
24+
let error = ResponseStatus::from(error);
25+
format_error!("Generate random status", error);
26+
Err(error)
27+
}
28+
}
29+
}
30+
}

src/providers/mbed_crypto_provider/mod.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ use log::{error, trace};
1111
use parsec_interface::operations::list_providers::ProviderInfo;
1212
use parsec_interface::operations::{
1313
psa_aead_decrypt, psa_aead_encrypt, psa_asymmetric_decrypt, psa_asymmetric_encrypt,
14-
psa_destroy_key, psa_export_key, psa_export_public_key, psa_generate_key, psa_hash_compare,
15-
psa_hash_compute, psa_import_key, psa_raw_key_agreement, psa_sign_hash, psa_verify_hash,
14+
psa_destroy_key, psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random,
15+
psa_hash_compare, psa_hash_compute, psa_import_key, psa_raw_key_agreement, psa_sign_hash,
16+
psa_verify_hash,
1617
};
1718
use parsec_interface::requests::{Opcode, ProviderID, ResponseStatus, Result};
1819
use psa_crypto::types::{key, status};
@@ -27,12 +28,12 @@ use uuid::Uuid;
2728
mod aead;
2829
mod asym_encryption;
2930
mod asym_sign;
31+
mod generate_random;
3032
mod hash;
3133
mod key_agreement;
32-
#[allow(dead_code)]
3334
mod key_management;
3435

35-
const SUPPORTED_OPCODES: [Opcode; 14] = [
36+
const SUPPORTED_OPCODES: [Opcode; 15] = [
3637
Opcode::PsaGenerateKey,
3738
Opcode::PsaDestroyKey,
3839
Opcode::PsaSignHash,
@@ -47,6 +48,7 @@ const SUPPORTED_OPCODES: [Opcode; 14] = [
4748
Opcode::PsaHashCompare,
4849
Opcode::PsaHashCompute,
4950
Opcode::PsaRawKeyAgreement,
51+
Opcode::PsaGenerateRandom,
5052
];
5153

5254
/// Mbed Crypto provider structure
@@ -284,6 +286,14 @@ impl Provide for MbedCryptoProvider {
284286
trace!("psa_raw_key_agreement");
285287
self.psa_raw_key_agreement(app_name, op)
286288
}
289+
290+
fn psa_generate_random(
291+
&self,
292+
op: psa_generate_random::Operation,
293+
) -> Result<psa_generate_random::Result> {
294+
trace!("psa_generate_random ingress");
295+
self.psa_generate_random_internal(op)
296+
}
287297
}
288298

289299
/// Mbed Crypto provider builder

src/providers/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ use crate::authenticators::ApplicationName;
9191
use parsec_interface::operations::{
9292
list_authenticators, list_opcodes, list_providers, ping, psa_aead_decrypt, psa_aead_encrypt,
9393
psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_destroy_key, psa_export_key,
94-
psa_export_public_key, psa_generate_key, psa_hash_compare, psa_hash_compute, psa_import_key,
95-
psa_raw_key_agreement, psa_sign_hash, psa_verify_hash,
94+
psa_export_public_key, psa_generate_key, psa_generate_random, psa_hash_compare,
95+
psa_hash_compute, psa_import_key, psa_raw_key_agreement, psa_sign_hash, psa_verify_hash,
9696
};
9797
use parsec_interface::requests::{ResponseStatus, Result};
9898

@@ -279,4 +279,13 @@ pub trait Provide {
279279
trace!("psa_raw_key_agreement ingress");
280280
Err(ResponseStatus::PsaErrorNotSupported)
281281
}
282+
283+
/// Execute a GenerateRandom operation.
284+
fn psa_generate_random(
285+
&self,
286+
_op: psa_generate_random::Operation,
287+
) -> Result<psa_generate_random::Result> {
288+
trace!("psa_generate_random ingress");
289+
Err(ResponseStatus::PsaErrorNotSupported)
290+
}
282291
}

0 commit comments

Comments
 (0)