Skip to content

Commit 6c8df64

Browse files
authored
Merge pull request #578 from RobertDrazkowskiGL/calib-psa-rawkey
[CryptoAuthLib provider] PsaRawKeyAgreement operation implementation
2 parents 4a7b313 + d76e82b commit 6c8df64

File tree

6 files changed

+102
-12
lines changed

6 files changed

+102
-12
lines changed

Cargo.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,16 @@ picky-asn1-x509 = { version = "0.4.0", optional = true }
4141
users = "0.11.0"
4242
libc = "0.2.86"
4343
anyhow = "1.0.38"
44-
rust-cryptoauthlib = { version = "0.4.2", optional = true }
44+
rust-cryptoauthlib = { version = "0.4.4", optional = true }
4545
spiffe = { version = "0.2.0", optional = true }
4646
prost = { version = "0.8.0", optional = true }
4747
rusqlite = { version = "0.25.3", features = ["bundled"] }
4848
num-traits = "0.2.14"
4949

5050
[dev-dependencies]
5151
rand = { version = "0.8.3", features = ["small_rng"] }
52-
rust-cryptoauthlib = { version = "0.4.2", features=["software-backend"]}
52+
rust-cryptoauthlib = { version = "0.4.4", features=["software-backend"]}
53+
5354

5455
[build-dependencies]
5556
bindgen = { version = "0.57.0", optional = true }

e2e_tests/tests/per_provider/normal_tests/key_agreement.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ const EXPECTED_OUTPUT_SECPR1: [u8; 32] = [
2323
0x2f, 0xef, 0x8e, 0x9e, 0xce, 0x7d, 0xce, 0x03, 0x81, 0x24, 0x64, 0xd0, 0x4b, 0x94, 0x42, 0xde,
2424
];
2525

26+
#[cfg(not(feature = "cryptoauthlib-provider"))]
2627
const OUR_KEY_DATA_BRAINPOOL_R1: [u8; 32] = [
2728
0x81, 0xdb, 0x1e, 0xe1, 0x00, 0x15, 0x0f, 0xf2, 0xea, 0x33, 0x8d, 0x70, 0x82, 0x71, 0xbe, 0x38,
2829
0x30, 0x0c, 0xb5, 0x42, 0x41, 0xd7, 0x99, 0x50, 0xf7, 0x7b, 0x06, 0x30, 0x39, 0x80, 0x4f, 0x1d,
2930
];
3031

32+
#[cfg(not(feature = "cryptoauthlib-provider"))]
3133
const PEER_PUBLIC_KEY_BRAINPOOL_R1: [u8; 65] = [
3234
0x04, 0x8d, 0x2d, 0x68, 0x8c, 0x6c, 0xf9, 0x3e, 0x11, 0x60, 0xad, 0x04, 0xcc, 0x44, 0x29, 0x11,
3335
0x7d, 0xc2, 0xc4, 0x18, 0x25, 0xe1, 0xe9, 0xfc, 0xa0, 0xad, 0xdd, 0x34, 0xe6, 0xf1, 0xb3, 0x9f,
@@ -36,6 +38,7 @@ const PEER_PUBLIC_KEY_BRAINPOOL_R1: [u8; 65] = [
3638
0x6a,
3739
];
3840

41+
#[cfg(not(feature = "cryptoauthlib-provider"))]
3942
const EXPECTED_OUTPUT_BRAINPOOL_R1: [u8; 32] = [
4043
0x89, 0xaf, 0xc3, 0x9d, 0x41, 0xd3, 0xb3, 0x27, 0x81, 0x4b, 0x80, 0x94, 0x0b, 0x04, 0x25, 0x90,
4144
0xf9, 0x65, 0x56, 0xec, 0x91, 0xe6, 0xae, 0x79, 0x39, 0xbc, 0xe3, 0x1f, 0x3a, 0x18, 0xbf, 0x2b,
@@ -49,7 +52,7 @@ fn key_agreement_not_supported() {
4952
client
5053
.raw_key_agreement(
5154
RawKeyAgreement::Ecdh,
52-
String::from("some key"),
55+
String::from("some key name"),
5356
&PEER_PUBLIC_KEY_SECPR1
5457
)
5558
.unwrap_err(),
@@ -84,6 +87,14 @@ fn raw_key_agreement_secpr1() {
8487
return;
8588
}
8689

90+
// Section needed for crytpoauthlib if first slot is configured as ECC because it has has unusual access behavior
91+
// and user need to be aware of that.
92+
// Use this section only if first slot is configured as ECC.
93+
#[cfg(feature = "cryptoauthlib-provider")]
94+
{
95+
let key_name_0 = auto_test_keyname!("0");
96+
client.generate_ecc_pair_secp_r1_key(key_name_0).unwrap();
97+
} // end of section
8798
client
8899
.import_ecc_pair_secp_r1_key(key_name.clone(), OUR_KEY_DATA_SECPR1.to_vec())
89100
.unwrap();
@@ -94,6 +105,7 @@ fn raw_key_agreement_secpr1() {
94105
assert_eq!(&EXPECTED_OUTPUT_SECPR1, shared_secret.as_slice());
95106
}
96107

108+
#[cfg(not(feature = "cryptoauthlib-provider"))]
97109
#[test]
98110
fn raw_key_agreement_brainpoolpr1() {
99111
let key_name = auto_test_keyname!();
@@ -127,6 +139,14 @@ fn raw_key_agreement_two_generated_parties() {
127139
return;
128140
}
129141

142+
// Section needed for crytpoauthlib if first slot is configured as ECC because it has has unusual access behavior
143+
// and user need to be aware of that.
144+
// Use this section only if first slot is configured as ECC.
145+
#[cfg(feature = "cryptoauthlib-provider")]
146+
{
147+
let key_name_0 = auto_test_keyname!("0");
148+
client.generate_ecc_pair_secp_r1_key(key_name_0).unwrap();
149+
} // end of section
130150
client
131151
.generate_ecc_pair_secp_r1_key(key_name_1.clone())
132152
.unwrap();
@@ -143,5 +163,6 @@ fn raw_key_agreement_two_generated_parties() {
143163
let shared_secret_2_then_1 = client
144164
.raw_key_agreement(RawKeyAgreement::Ecdh, key_name_2, &public_key_1)
145165
.unwrap();
166+
146167
assert_eq!(shared_secret_1_then_2, shared_secret_2_then_1);
147168
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2022 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use super::Provider;
4+
use crate::authenticators::ApplicationIdentity;
5+
use crate::key_info_managers::KeyIdentity;
6+
use parsec_interface::operations::psa_algorithm::RawKeyAgreement;
7+
use parsec_interface::operations::psa_raw_key_agreement;
8+
use parsec_interface::requests::{ResponseStatus, Result};
9+
use parsec_interface::secrecy::Secret;
10+
11+
impl Provider {
12+
pub(super) fn psa_raw_key_agreement_internal(
13+
&self,
14+
application_identity: &ApplicationIdentity,
15+
op: psa_raw_key_agreement::Operation,
16+
) -> Result<psa_raw_key_agreement::Result> {
17+
let key_identity = KeyIdentity::new(
18+
application_identity.clone(),
19+
self.provider_identity.clone(),
20+
op.private_key_name.clone(),
21+
);
22+
let key_id = self.key_info_store.get_key_id::<u8>(&key_identity)?;
23+
let key_attributes = self.key_info_store.get_key_attributes(&key_identity)?;
24+
op.validate(key_attributes)?;
25+
26+
match op.alg {
27+
RawKeyAgreement::Ecdh => {
28+
let parameters = rust_cryptoauthlib::EcdhParams {
29+
out_target: rust_cryptoauthlib::EcdhTarget::Output,
30+
slot_id: Some(key_id),
31+
..Default::default()
32+
};
33+
let mut key_data = op.peer_key.to_vec();
34+
if key_data.len() == 65 {
35+
key_data = op.peer_key[1..].to_vec();
36+
}
37+
match self.device.ecdh(parameters, &key_data) {
38+
Ok(result) => {
39+
let shared_secret = result.pms.unwrap().to_vec();
40+
Ok(psa_raw_key_agreement::Result {
41+
shared_secret: Secret::new(shared_secret),
42+
})
43+
}
44+
Err(status) => {
45+
format_error!("Raw key agreement status: ", status);
46+
Err(ResponseStatus::PsaErrorGenericError)
47+
}
48+
}
49+
}
50+
_ => Err(ResponseStatus::PsaErrorNotSupported),
51+
}
52+
}
53+
}

src/providers/cryptoauthlib/key_management.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ fn get_calib_key_type(attributes: &Attributes) -> Result<rust_cryptoauthlib::Key
327327
if attributes.bits == 256 || attributes.bits == 0 {
328328
Ok(rust_cryptoauthlib::KeyType::P256EccKey)
329329
} else {
330-
Err(ResponseStatus::PsaErrorNotSupported)
330+
Err(ResponseStatus::PsaErrorInvalidArgument)
331331
}
332332
}
333333
_ => Err(ResponseStatus::PsaErrorNotSupported),

src/providers/cryptoauthlib/mod.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use uuid::Uuid;
2121
use parsec_interface::operations::{
2222
psa_aead_decrypt, psa_aead_encrypt, psa_cipher_decrypt, psa_cipher_encrypt, psa_destroy_key,
2323
psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random, psa_hash_compare,
24-
psa_hash_compute, psa_import_key, psa_sign_hash, psa_sign_message, psa_verify_hash,
25-
psa_verify_message,
24+
psa_hash_compute, psa_import_key, psa_raw_key_agreement, psa_sign_hash, psa_sign_message,
25+
psa_verify_hash, psa_verify_message,
2626
};
2727

2828
mod access_keys;
@@ -31,6 +31,7 @@ mod asym_sign;
3131
mod cipher;
3232
mod generate_random;
3333
mod hash;
34+
mod key_agreement;
3435
mod key_management;
3536
mod key_slot;
3637
mod key_slot_storage;
@@ -229,6 +230,7 @@ impl Provider {
229230
&& self.supported_opcodes.insert(Opcode::PsaExportKey)
230231
&& self.supported_opcodes.insert(Opcode::PsaAeadEncrypt)
231232
&& self.supported_opcodes.insert(Opcode::PsaAeadDecrypt)
233+
&& self.supported_opcodes.insert(Opcode::PsaRawKeyAgreement)
232234
{
233235
Some(())
234236
} else {
@@ -486,6 +488,19 @@ impl Provide for Provider {
486488
self.psa_aead_decrypt_internal(application_identity, op)
487489
}
488490
}
491+
492+
fn psa_raw_key_agreement(
493+
&self,
494+
application_identity: &ApplicationIdentity,
495+
op: psa_raw_key_agreement::Operation,
496+
) -> Result<psa_raw_key_agreement::Result> {
497+
trace!("psa_raw_key_agreement ingress");
498+
if !self.supported_opcodes.contains(&Opcode::PsaRawKeyAgreement) {
499+
Err(ResponseStatus::PsaErrorNotSupported)
500+
} else {
501+
self.psa_raw_key_agreement_internal(application_identity, op)
502+
}
503+
}
489504
}
490505

491506
/// CryptoAuthentication Library Provider builder

0 commit comments

Comments
 (0)