Skip to content

Commit 4f48d1d

Browse files
authored
Merge pull request #171 from ionut-arm/tpm-ecc
Add ECDSA support for TPM provider
2 parents 578d6d5 + 19fdc72 commit 4f48d1d

File tree

7 files changed

+318
-103
lines changed

7 files changed

+318
-103
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 2 deletions
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.14.0"
21+
parsec-interface = "0.14.1"
2222
rand = "0.7.2"
2323
base64 = "0.10.1"
2424
uuid = "0.7.4"
@@ -33,7 +33,7 @@ log = { version = "0.4.8", features = ["serde"] }
3333
pkcs11 = { version = "0.4.0", optional = true }
3434
picky-asn1-der = { version = "0.2.2", optional = true }
3535
picky-asn1 = { version = "0.2.1", optional = true }
36-
tss-esapi = { version = "4.0.0-alpha.1", optional = true }
36+
tss-esapi = { version = "4.0.2-alpha.1", optional = true }
3737
bincode = "1.1.4"
3838
structopt = "0.3.5"
3939
derivative = "2.1.1"

e2e_tests/tests/per_provider/normal_tests/key_attributes.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
use e2e_tests::TestClient;
44
use parsec_client::core::interface::operations::psa_algorithm::{
5-
Algorithm, AsymmetricSignature, Cipher, Hash,
5+
Algorithm, AsymmetricSignature, Hash,
66
};
77
use parsec_client::core::interface::operations::psa_key_attributes::{
88
KeyAttributes, KeyPolicy, KeyType, UsageFlags,
@@ -100,7 +100,10 @@ fn wrong_permitted_algorithm() {
100100

101101
let key_type = KeyType::RsaKeyPair;
102102
// Do not permit RSA PKCS 1v15 signing algorithm with SHA-256.
103-
let permitted_algorithm = Algorithm::Cipher(Cipher::Ctr);
103+
let permitted_algorithm =
104+
Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
105+
hash_alg: Hash::Sha512,
106+
});
104107
let key_attributes = KeyAttributes {
105108
key_type,
106109
key_bits: 1024,

src/providers/tpm_provider/asym_sign.rs

Lines changed: 24 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,71 +7,51 @@ use log::error;
77
use parsec_interface::operations::psa_algorithm::*;
88
use parsec_interface::operations::{psa_sign_hash, psa_verify_hash};
99
use parsec_interface::requests::{ProviderID, ResponseStatus, Result};
10-
use tss_esapi::{constants::TPM2_ALG_SHA256, utils::AsymSchemeUnion, utils::Signature};
1110

1211
impl TpmProvider {
1312
pub(super) fn psa_sign_hash_internal(
1413
&self,
1514
app_name: ApplicationName,
1615
op: psa_sign_hash::Operation,
1716
) -> Result<psa_sign_hash::Result> {
18-
let key_name = op.key_name;
19-
let hash = op.hash;
20-
let alg = op.alg;
21-
let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, key_name);
17+
let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, op.key_name.clone());
2218

2319
let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
2420
let mut esapi_context = self
2521
.esapi_context
2622
.lock()
2723
.expect("ESAPI Context lock poisoned");
2824

29-
if alg
30-
!= (AsymmetricSignature::RsaPkcs1v15Sign {
31-
hash_alg: Hash::Sha256,
32-
})
33-
{
34-
error!(
35-
"The TPM provider currently only supports signature algorithm to be RSA PKCS#1 v1.5 and the text hashed with SHA-256.");
36-
return Err(ResponseStatus::PsaErrorNotSupported);
37-
}
38-
39-
if hash.len() != 32 {
40-
error!("The SHA-256 hash must be 32 bytes long.");
41-
return Err(ResponseStatus::PsaErrorInvalidArgument);
42-
}
43-
4425
let (password_context, key_attributes) =
4526
key_management::get_password_context(&*store_handle, key_triple)?;
4627

47-
key_attributes.can_sign_hash()?;
48-
key_attributes.permits_alg(alg.into())?;
49-
key_attributes.compatible_with_alg(alg.into())?;
50-
51-
match alg {
52-
AsymmetricSignature::RsaPkcs1v15Sign {
53-
hash_alg: Hash::Sha256,
54-
} => (),
28+
match op.alg {
29+
AsymmetricSignature::RsaPkcs1v15Sign { .. } => (),
30+
AsymmetricSignature::Ecdsa { .. } => (),
5531
_ => {
5632
error!(
57-
"The TPM provider currently only supports \"RSA PKCS#1 v1.5 signature with hashing\" algorithm with SHA-256 as hashing algorithm for the PsaSignHash operation.");
33+
"Requested algorithm is not supported by the TPM provider: {:?}",
34+
op.alg
35+
);
5836
return Err(ResponseStatus::PsaErrorNotSupported);
5937
}
6038
}
6139

40+
op.validate(key_attributes)?;
41+
6242
let signature = esapi_context
6343
.sign(
6444
password_context.context,
6545
&password_context.auth_value,
66-
&hash,
46+
&op.hash,
6747
)
6848
.or_else(|e| {
6949
error!("Error signing: {}.", e);
7050
Err(utils::to_response_status(e))
7151
})?;
7252

7353
Ok(psa_sign_hash::Result {
74-
signature: signature.signature,
54+
signature: utils::signature_data_to_bytes(signature.signature, key_attributes)?,
7555
})
7656
}
7757

@@ -80,59 +60,36 @@ impl TpmProvider {
8060
app_name: ApplicationName,
8161
op: psa_verify_hash::Operation,
8262
) -> Result<psa_verify_hash::Result> {
83-
let key_name = op.key_name;
84-
let hash = op.hash;
85-
let alg = op.alg;
86-
let signature = op.signature;
87-
let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, key_name);
63+
let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, op.key_name.clone());
8864

8965
let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
9066
let mut esapi_context = self
9167
.esapi_context
9268
.lock()
9369
.expect("ESAPI Context lock poisoned");
9470

95-
if alg
96-
!= (AsymmetricSignature::RsaPkcs1v15Sign {
97-
hash_alg: Hash::Sha256,
98-
})
99-
{
100-
error!(
101-
"The TPM provider currently only supports signature algorithm to be RSA PKCS#1 v1.5 and the text hashed with SHA-256.");
102-
return Err(ResponseStatus::PsaErrorNotSupported);
103-
}
104-
105-
if hash.len() != 32 {
106-
error!("The SHA-256 hash must be 32 bytes long.");
107-
return Err(ResponseStatus::PsaErrorInvalidArgument);
108-
}
109-
110-
let signature = Signature {
111-
scheme: AsymSchemeUnion::RSASSA(TPM2_ALG_SHA256),
112-
signature,
113-
};
114-
11571
let (password_context, key_attributes) =
11672
key_management::get_password_context(&*store_handle, key_triple)?;
11773

118-
key_attributes.can_verify_hash()?;
119-
key_attributes.permits_alg(alg.into())?;
120-
key_attributes.compatible_with_alg(alg.into())?;
121-
122-
match alg {
123-
AsymmetricSignature::RsaPkcs1v15Sign {
124-
hash_alg: Hash::Sha256,
125-
} => (),
74+
match op.alg {
75+
AsymmetricSignature::RsaPkcs1v15Sign { .. } => (),
76+
AsymmetricSignature::Ecdsa { .. } => (),
12677
_ => {
12778
error!(
128-
"The TPM provider currently only supports \"RSA PKCS#1 v1.5 signature with hashing\" algorithm with SHA-256 as hashing algorithm for the PsaVerifyHash operation.");
79+
"Requested algorithm is not supported by the TPM provider: {:?}",
80+
op.alg
81+
);
12982
return Err(ResponseStatus::PsaErrorNotSupported);
13083
}
13184
}
13285

86+
op.validate(key_attributes)?;
87+
88+
let signature = utils::parsec_to_tpm_signature(op.signature, key_attributes, op.alg)?;
89+
13390
let _ = esapi_context
134-
.verify_signature(password_context.context, &hash, signature)
135-
.or_else(|e| Err(utils::to_response_status(e)))?;
91+
.verify_signature(password_context.context, &op.hash, signature)
92+
.map_err(utils::to_response_status)?;
13693

13794
Ok(psa_verify_hash::Result {})
13895
}

src/providers/tpm_provider/key_management.rs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use parsec_interface::operations::{
1313
psa_destroy_key, psa_export_public_key, psa_generate_key, psa_import_key,
1414
};
1515
use parsec_interface::requests::{ProviderID, ResponseStatus, Result};
16-
use picky_asn1::wrapper::IntegerAsn1;
1716

1817
// Public exponent value for all RSA keys.
1918
const PUBLIC_EXPONENT: [u8; 3] = [0x01, 0x00, 0x01];
@@ -69,17 +68,9 @@ impl TpmProvider {
6968
app_name: ApplicationName,
7069
op: psa_generate_key::Operation,
7170
) -> Result<psa_generate_key::Result> {
72-
if op.attributes.key_type != KeyType::RsaKeyPair {
73-
error!("The TPM provider currently only supports creating RSA key pairs.");
74-
return Err(ResponseStatus::PsaErrorNotSupported);
75-
}
76-
7771
let key_name = op.key_name;
7872
let attributes = op.attributes;
7973
let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, key_name);
80-
// This should never panic on 32 bits or more machines.
81-
let key_size = std::convert::TryFrom::try_from(op.attributes.key_bits)
82-
.expect("Conversion to usize failed.");
8374

8475
let mut store_handle = self
8576
.key_info_store
@@ -91,7 +82,7 @@ impl TpmProvider {
9182
.expect("ESAPI Context lock poisoned");
9283

9384
let (key_context, auth_value) = esapi_context
94-
.create_rsa_signing_key(key_size, AUTH_VAL_LEN)
85+
.create_signing_key(utils::parsec_to_tpm_params(attributes)?, AUTH_VAL_LEN)
9586
.or_else(|e| {
9687
error!("Error creating a RSA signing key: {}.", e);
9788
Err(utils::to_response_status(e))
@@ -199,7 +190,7 @@ impl TpmProvider {
199190
.lock()
200191
.expect("ESAPI Context lock poisoned");
201192

202-
let (password_context, _key_attributes) = get_password_context(&*store_handle, key_triple)?;
193+
let (password_context, key_attributes) = get_password_context(&*store_handle, key_triple)?;
203194

204195
let pub_key_data = esapi_context
205196
.read_public_key(password_context.context)
@@ -208,18 +199,9 @@ impl TpmProvider {
208199
Err(utils::to_response_status(e))
209200
})?;
210201

211-
let key = RsaPublicKey {
212-
// To produce a valid ASN.1 RSAPublicKey structure, 0x00 is put in front of the positive
213-
// modulus if highest significant bit is one, to differentiate it from a negative number.
214-
modulus: IntegerAsn1::from_unsigned_bytes_be(pub_key_data),
215-
public_exponent: IntegerAsn1::from_signed_bytes_be(PUBLIC_EXPONENT.to_vec()),
216-
};
217-
let key_data = picky_asn1_der::to_vec(&key).or_else(|err| {
218-
error!("Could not serialise key elements: {}.", err);
219-
Err(ResponseStatus::PsaErrorCommunicationFailure)
220-
})?;
221-
222-
Ok(psa_export_public_key::Result { data: key_data })
202+
Ok(psa_export_public_key::Result {
203+
data: utils::pub_key_to_bytes(pub_key_data, key_attributes)?,
204+
})
223205
}
224206

225207
pub(super) fn psa_destroy_key_internal(
@@ -234,10 +216,9 @@ impl TpmProvider {
234216
.write()
235217
.expect("Key store lock poisoned");
236218

237-
let error_closure = |e| Err(key_info_managers::to_response_status(e));
238219
if store_handle
239220
.remove(&key_triple)
240-
.or_else(error_closure)?
221+
.map_err(key_info_managers::to_response_status)?
241222
.is_none()
242223
{
243224
error!(

0 commit comments

Comments
 (0)