Skip to content

Commit 72ebbee

Browse files
authored
Merge pull request #243 from joechrisellis/import_private_key_support
Import private key support for TPM provider
2 parents 54cc197 + 8197ce9 commit 72ebbee

File tree

7 files changed

+319
-75
lines changed

7 files changed

+319
-75
lines changed

Cargo.lock

Lines changed: 23 additions & 12 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 & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ env_logger = "0.7.1"
3232
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 }
35-
picky-asn1 = { version = "0.2.1", optional = true }
36-
tss-esapi = { version = "4.0.8-alpha.1", optional = true }
35+
picky-asn1 = { version = "0.3.0", optional = true }
36+
tss-esapi = { version = "4.0.9-alpha.1", optional = true }
3737
bincode = "1.1.4"
3838
structopt = "0.3.5"
3939
derivative = "2.1.1"
@@ -42,7 +42,7 @@ hex = "0.4.2"
4242
picky = "5.0.0"
4343
psa-crypto = { version = "0.5.0" , default-features = false, features = ["operations"], optional = true }
4444
zeroize = { version = "1.1.0", features = ["zeroize_derive"] }
45-
picky-asn1-x509 = { version = "0.3.0", optional = true }
45+
picky-asn1-x509 = { version = "0.3.2", optional = true }
4646
users = "0.10.0"
4747
libc = "0.2.72"
4848

src/providers/pkcs11_provider/key_management.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,23 @@ impl Pkcs11Provider {
161161
app_name: ApplicationName,
162162
op: psa_import_key::Operation,
163163
) -> Result<psa_import_key::Result> {
164-
if op.attributes.key_type != Type::RsaPublicKey {
165-
error!("The PKCS 11 provider currently only supports importing RSA public key.");
166-
return Err(ResponseStatus::PsaErrorNotSupported);
164+
match op.attributes.key_type {
165+
Type::RsaPublicKey => self.psa_import_key_internal_rsa_public(app_name, op),
166+
_ => {
167+
error!(
168+
"The pkcs11 provider does not support the {:?} key type.",
169+
op.attributes.key_type
170+
);
171+
Err(ResponseStatus::PsaErrorNotSupported)
172+
}
167173
}
174+
}
168175

176+
pub(super) fn psa_import_key_internal_rsa_public(
177+
&self,
178+
app_name: ApplicationName,
179+
op: psa_import_key::Operation,
180+
) -> Result<psa_import_key::Result> {
169181
let key_name = op.key_name;
170182
let key_attributes = op.attributes;
171183
let key_triple = KeyTriple::new(app_name, ProviderID::Pkcs11, key_name);
@@ -342,8 +354,8 @@ impl Pkcs11Provider {
342354

343355
// To produce a valid ASN.1 RSAPublicKey structure, 0x00 is put in front of the positive
344356
// integer if highest significant bit is one, to differentiate it from a negative number.
345-
let modulus = IntegerAsn1::from_unsigned_bytes_be(modulus);
346-
let public_exponent = IntegerAsn1::from_unsigned_bytes_be(public_exponent);
357+
let modulus = IntegerAsn1::from_bytes_be_unsigned(modulus);
358+
let public_exponent = IntegerAsn1::from_bytes_be_unsigned(public_exponent);
347359

348360
let key = RSAPublicKey {
349361
modulus,

src/providers/tpm_provider/key_management.rs

Lines changed: 78 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
use super::utils;
44
use super::utils::PasswordContext;
5+
use super::utils::{validate_private_key, validate_public_key, PUBLIC_EXPONENT};
56
use super::TpmProvider;
67
use crate::authenticators::ApplicationName;
78
use crate::key_info_managers;
@@ -14,11 +15,10 @@ use parsec_interface::operations::{
1415
};
1516
use parsec_interface::requests::{ProviderID, ResponseStatus, Result};
1617
use parsec_interface::secrecy::ExposeSecret;
17-
use picky_asn1_x509::RSAPublicKey;
18+
use picky_asn1_x509::{RSAPrivateKey, RSAPublicKey};
19+
use tss_esapi::abstraction::transient::RsaExponent;
1820
use zeroize::Zeroize;
1921

20-
// Public exponent value for all RSA keys.
21-
const PUBLIC_EXPONENT: [u8; 3] = [0x01, 0x00, 0x01];
2222
const AUTH_VAL_LEN: usize = 32;
2323

2424
// Inserts a new mapping in the Key Info manager that stores the PasswordContext.
@@ -117,11 +117,24 @@ impl TpmProvider {
117117
app_name: ApplicationName,
118118
op: psa_import_key::Operation,
119119
) -> Result<psa_import_key::Result> {
120-
if op.attributes.key_type != Type::RsaPublicKey {
121-
error!("The TPM provider currently only supports importing RSA public key.");
122-
return Err(ResponseStatus::PsaErrorNotSupported);
120+
match op.attributes.key_type {
121+
Type::RsaPublicKey => self.psa_import_key_internal_rsa_public(app_name, op),
122+
Type::RsaKeyPair => self.psa_import_key_internal_rsa_keypair(app_name, op),
123+
_ => {
124+
error!(
125+
"The TPM provider does not support importing for the {:?} key type.",
126+
op.attributes.key_type
127+
);
128+
Err(ResponseStatus::PsaErrorNotSupported)
129+
}
123130
}
131+
}
124132

133+
pub(super) fn psa_import_key_internal_rsa_public(
134+
&self,
135+
app_name: ApplicationName,
136+
op: psa_import_key::Operation,
137+
) -> Result<psa_import_key::Result> {
125138
let key_name = op.key_name;
126139
let attributes = op.attributes;
127140
let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, key_name);
@@ -142,50 +155,9 @@ impl TpmProvider {
142155
ResponseStatus::PsaErrorInvalidArgument
143156
})?;
144157

145-
if public_key.modulus.is_negative() || public_key.public_exponent.is_negative() {
146-
error!("Only positive modulus and public exponent are supported.");
147-
return Err(ResponseStatus::PsaErrorInvalidArgument);
148-
}
158+
validate_public_key(&public_key, &attributes)?;
149159

150-
if public_key.public_exponent.as_unsigned_bytes_be() != PUBLIC_EXPONENT {
151-
if crate::utils::GlobalConfig::log_error_details() {
152-
error!("The TPM Provider only supports 0x101 as public exponent for RSA public keys, {:?} given.", public_key.public_exponent.as_unsigned_bytes_be());
153-
} else {
154-
error!(
155-
"The TPM Provider only supports 0x101 as public exponent for RSA public keys"
156-
);
157-
}
158-
return Err(ResponseStatus::PsaErrorNotSupported);
159-
}
160160
let key_data = public_key.modulus.as_unsigned_bytes_be();
161-
let len = key_data.len();
162-
163-
let key_bits = attributes.bits;
164-
if key_bits != 0 && len * 8 != key_bits {
165-
if crate::utils::GlobalConfig::log_error_details() {
166-
error!(
167-
"`bits` field of key attributes (value: {}) must be either 0 or equal to the size of the key in `data` (value: {}).",
168-
attributes.bits,
169-
len * 8
170-
);
171-
} else {
172-
error!("`bits` field of key attributes must be either 0 or equal to the size of the key in `data`.");
173-
}
174-
return Err(ResponseStatus::PsaErrorInvalidArgument);
175-
}
176-
177-
if len != 128 && len != 256 {
178-
if crate::utils::GlobalConfig::log_error_details() {
179-
error!(
180-
"The TPM provider only supports 1024 and 2048 bits RSA public keys ({} bits given).",
181-
len * 8
182-
);
183-
} else {
184-
error!("The TPM provider only supports 1024 and 2048 bits RSA public keys");
185-
}
186-
return Err(ResponseStatus::PsaErrorNotSupported);
187-
}
188-
189161
let pub_key_context = esapi_context
190162
.load_external_rsa_public_key(&key_data)
191163
.map_err(|e| {
@@ -206,6 +178,64 @@ impl TpmProvider {
206178
Ok(psa_import_key::Result {})
207179
}
208180

181+
pub(super) fn psa_import_key_internal_rsa_keypair(
182+
&self,
183+
app_name: ApplicationName,
184+
op: psa_import_key::Operation,
185+
) -> Result<psa_import_key::Result> {
186+
let key_name = op.key_name;
187+
let attributes = op.attributes;
188+
let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, key_name);
189+
let key_data = op.data;
190+
191+
let mut store_handle = self
192+
.key_info_store
193+
.write()
194+
.expect("Key store lock poisoned");
195+
let mut esapi_context = self
196+
.esapi_context
197+
.lock()
198+
.expect("ESAPI Context lock poisoned");
199+
200+
let private_key: RSAPrivateKey = picky_asn1_der::from_bytes(key_data.expose_secret())
201+
.map_err(|err| {
202+
format_error!("Could not deserialise key elements", err);
203+
ResponseStatus::PsaErrorInvalidArgument
204+
})?;
205+
206+
// Derive the public key from the keypair.
207+
let public_key = RSAPublicKey {
208+
modulus: private_key.modulus.clone(),
209+
public_exponent: private_key.public_exponent.clone(),
210+
};
211+
212+
// Validate the public and the private key.
213+
validate_public_key(&public_key, &attributes)?;
214+
validate_private_key(&private_key, &attributes)?;
215+
216+
let key_prime = private_key.prime_1.as_unsigned_bytes_be();
217+
let public_modulus = private_key.modulus.as_unsigned_bytes_be();
218+
219+
let keypair_context = esapi_context
220+
.load_external_rsa(key_prime, public_modulus, RsaExponent::new(PUBLIC_EXPONENT))
221+
.map_err(|e| {
222+
format_error!("Error creating a RSA signing key", e);
223+
utils::to_response_status(e)
224+
})?;
225+
226+
insert_password_context(
227+
&mut *store_handle,
228+
key_triple,
229+
PasswordContext {
230+
context: keypair_context,
231+
auth_value: Vec::new(),
232+
},
233+
attributes,
234+
)?;
235+
236+
Ok(psa_import_key::Result {})
237+
}
238+
209239
pub(super) fn psa_export_public_key_internal(
210240
&self,
211241
app_name: ApplicationName,

src/providers/tpm_provider/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ impl TpmProviderBuilder {
301301
.with_root_key_auth_size(ROOT_KEY_AUTH_SIZE)
302302
.with_hierarchy_auth(hierarchy_auth)
303303
.with_hierarchy(tss_esapi::utils::Hierarchy::Owner)
304-
.with_session_hash_alg(HashingAlgorithm::Sha256.into())
304+
.with_session_hash_alg(HashingAlgorithm::Sha256)
305305
.with_default_context_cipher(default_cipher)
306306
.build()
307307
.map_err(|e| {

0 commit comments

Comments
 (0)