From 1c01cfe303e04e49374feb4060cc96a44b2775c9 Mon Sep 17 00:00:00 2001 From: Joe Ellis Date: Tue, 8 Sep 2020 17:39:08 +0100 Subject: [PATCH 1/4] Bump picky version number Signed-off-by: Joe Ellis --- Cargo.toml | 6 +++--- src/providers/pkcs11_provider/key_management.rs | 4 ++-- src/providers/tpm_provider/utils.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index db7c22b9..49c34575 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,8 +32,8 @@ env_logger = "0.7.1" log = { version = "0.4.8", features = ["serde"] } pkcs11 = { version = "0.4.0", optional = true } picky-asn1-der = { version = "0.2.2", optional = true } -picky-asn1 = { version = "0.2.1", optional = true } -tss-esapi = { version = "4.0.8-alpha.1", optional = true } +picky-asn1 = { version = "0.3.0", optional = true } +tss-esapi = { version = "4.0.9-alpha.1", optional = true } bincode = "1.1.4" structopt = "0.3.5" derivative = "2.1.1" @@ -42,7 +42,7 @@ hex = "0.4.2" picky = "5.0.0" psa-crypto = { version = "0.5.0" , default-features = false, features = ["operations"], optional = true } zeroize = { version = "1.1.0", features = ["zeroize_derive"] } -picky-asn1-x509 = { version = "0.3.0", optional = true } +picky-asn1-x509 = { version = "0.3.2", optional = true } users = "0.10.0" libc = "0.2.72" diff --git a/src/providers/pkcs11_provider/key_management.rs b/src/providers/pkcs11_provider/key_management.rs index 5f528e46..e4ecee76 100644 --- a/src/providers/pkcs11_provider/key_management.rs +++ b/src/providers/pkcs11_provider/key_management.rs @@ -342,8 +342,8 @@ impl Pkcs11Provider { // To produce a valid ASN.1 RSAPublicKey structure, 0x00 is put in front of the positive // integer if highest significant bit is one, to differentiate it from a negative number. - let modulus = IntegerAsn1::from_unsigned_bytes_be(modulus); - let public_exponent = IntegerAsn1::from_unsigned_bytes_be(public_exponent); + let modulus = IntegerAsn1::from_bytes_be_unsigned(modulus); + let public_exponent = IntegerAsn1::from_bytes_be_unsigned(public_exponent); let key = RSAPublicKey { modulus, diff --git a/src/providers/tpm_provider/utils.rs b/src/providers/tpm_provider/utils.rs index 57a90902..4e949894 100644 --- a/src/providers/tpm_provider/utils.rs +++ b/src/providers/tpm_provider/utils.rs @@ -178,8 +178,8 @@ fn convert_curve_to_tpm(key_attributes: Attributes) -> Result { pub fn pub_key_to_bytes(pub_key: PublicKey, key_attributes: Attributes) -> Result> { match pub_key { PublicKey::Rsa(key) => picky_asn1_der::to_vec(&RSAPublicKey { - modulus: IntegerAsn1::from_unsigned_bytes_be(key), - public_exponent: IntegerAsn1::from_signed_bytes_be(PUBLIC_EXPONENT.to_vec()), + modulus: IntegerAsn1::from_bytes_be_unsigned(key), + public_exponent: IntegerAsn1::from_bytes_be_signed(PUBLIC_EXPONENT.to_vec()), }) .or(Err(ResponseStatus::PsaErrorGenericError)), PublicKey::Ecc { x, y } => { From 7a46e717f1e88dcce974f56fa5f145234888454b Mon Sep 17 00:00:00 2001 From: Joe Ellis Date: Mon, 17 Aug 2020 14:35:20 +0100 Subject: [PATCH 2/4] Add scaffolding for supporting different key types for ImportKey Signed-off-by: Joe Ellis --- .../pkcs11_provider/key_management.rs | 18 +++++++++++++++--- src/providers/tpm_provider/key_management.rs | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/providers/pkcs11_provider/key_management.rs b/src/providers/pkcs11_provider/key_management.rs index e4ecee76..65f552c0 100644 --- a/src/providers/pkcs11_provider/key_management.rs +++ b/src/providers/pkcs11_provider/key_management.rs @@ -161,11 +161,23 @@ impl Pkcs11Provider { app_name: ApplicationName, op: psa_import_key::Operation, ) -> Result { - if op.attributes.key_type != Type::RsaPublicKey { - error!("The PKCS 11 provider currently only supports importing RSA public key."); - return Err(ResponseStatus::PsaErrorNotSupported); + match op.attributes.key_type { + Type::RsaPublicKey => self.psa_import_key_internal_rsa_public(app_name, op), + _ => { + error!( + "The pkcs11 provider does not support the {:?} key type.", + op.attributes.key_type + ); + Err(ResponseStatus::PsaErrorNotSupported) + } } + } + pub(super) fn psa_import_key_internal_rsa_public( + &self, + app_name: ApplicationName, + op: psa_import_key::Operation, + ) -> Result { let key_name = op.key_name; let key_attributes = op.attributes; let key_triple = KeyTriple::new(app_name, ProviderID::Pkcs11, key_name); diff --git a/src/providers/tpm_provider/key_management.rs b/src/providers/tpm_provider/key_management.rs index 62e65878..f22495f6 100644 --- a/src/providers/tpm_provider/key_management.rs +++ b/src/providers/tpm_provider/key_management.rs @@ -117,11 +117,23 @@ impl TpmProvider { app_name: ApplicationName, op: psa_import_key::Operation, ) -> Result { - if op.attributes.key_type != Type::RsaPublicKey { - error!("The TPM provider currently only supports importing RSA public key."); - return Err(ResponseStatus::PsaErrorNotSupported); + match op.attributes.key_type { + Type::RsaPublicKey => self.psa_import_key_internal_rsa_public(app_name, op), + _ => { + error!( + "The TPM provider does not support the {:?} key type.", + op.attributes.key_type + ); + Err(ResponseStatus::PsaErrorNotSupported) + } } + } + pub(super) fn psa_import_key_internal_rsa_public( + &self, + app_name: ApplicationName, + op: psa_import_key::Operation, + ) -> Result { let key_name = op.key_name; let attributes = op.attributes; let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, key_name); From 71c4effccdc6937a317647d37bab7d44e12d46d3 Mon Sep 17 00:00:00 2001 From: Joe Ellis Date: Tue, 8 Sep 2020 13:48:39 +0100 Subject: [PATCH 3/4] Add support for importing private keys with TPM provider Signed-off-by: Joe Ellis --- Cargo.lock | 35 ++++-- src/providers/tpm_provider/key_management.rs | 110 +++++++++++-------- src/providers/tpm_provider/mod.rs | 2 +- src/providers/tpm_provider/utils.rs | 104 +++++++++++++++++- 4 files changed, 188 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c11e9ca..376066ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,9 +638,9 @@ dependencies = [ [[package]] name = "num-derive" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0396233fb2d5b0ae3f05ff6aba9a09185f7f6e70f87fb01147d545f85364665" +checksum = "6f09b9841adb6b5e1f89ef7087ea636e0fd94b2851f887c1e3eb5d5f8228fab3" dependencies = [ "proc-macro2", "quote", @@ -764,9 +764,9 @@ dependencies = [ "log", "parsec-interface", "picky", - "picky-asn1", + "picky-asn1 0.3.0", "picky-asn1-der", - "picky-asn1-x509 0.3.0", + "picky-asn1-x509 0.3.2", "pkcs11", "psa-crypto", "rand", @@ -823,7 +823,7 @@ dependencies = [ "base64 0.12.3", "http", "oid", - "picky-asn1", + "picky-asn1 0.2.2", "picky-asn1-der", "picky-asn1-x509 0.1.0", "rand", @@ -846,13 +846,24 @@ dependencies = [ "serde_bytes", ] +[[package]] +name = "picky-asn1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0718a593406db1ad8be482278f79215a0901e978925462159d8598cacb004ea" +dependencies = [ + "oid", + "serde", + "serde_bytes", +] + [[package]] name = "picky-asn1-der" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1870d13b5ce802665d715a6a0b551ad48f27d0f5689a5951697cf00cab64f09a" dependencies = [ - "picky-asn1", + "picky-asn1 0.2.2", "serde", "serde_bytes", ] @@ -865,20 +876,20 @@ checksum = "969171630cdf5c269611dfffdc1e6d749365fc4059b86fe3620d8afa3ddce4e6" dependencies = [ "base64 0.12.3", "oid", - "picky-asn1", + "picky-asn1 0.2.2", "picky-asn1-der", "serde", ] [[package]] name = "picky-asn1-x509" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b0b354f137550bb42e1f3bafd83c4047006b55903c5b2b41f7997957c716e88" +checksum = "d79146ca2d1a8fdbe9f2653a04cc8914acd9e5702b052c08100d99f629b626bf" dependencies = [ "base64 0.12.3", "oid", - "picky-asn1", + "picky-asn1 0.3.0", "picky-asn1-der", "serde", ] @@ -1520,9 +1531,9 @@ dependencies = [ [[package]] name = "tss-esapi" -version = "4.0.8-alpha.1" +version = "4.0.9-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e699debe6392012e06a57157ce6f288f9ca0e0b2ae1ad3304ff07a977bcfec" +checksum = "a09d4314f5c2e87e86838a56363c35a941004a64a89af135ab9e2d0b6bddc5f4" dependencies = [ "bindgen", "bitfield", diff --git a/src/providers/tpm_provider/key_management.rs b/src/providers/tpm_provider/key_management.rs index f22495f6..3fa94779 100644 --- a/src/providers/tpm_provider/key_management.rs +++ b/src/providers/tpm_provider/key_management.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use super::utils; use super::utils::PasswordContext; +use super::utils::{validate_private_key, validate_public_key, PUBLIC_EXPONENT}; use super::TpmProvider; use crate::authenticators::ApplicationName; use crate::key_info_managers; @@ -14,11 +15,10 @@ use parsec_interface::operations::{ }; use parsec_interface::requests::{ProviderID, ResponseStatus, Result}; use parsec_interface::secrecy::ExposeSecret; -use picky_asn1_x509::RSAPublicKey; +use picky_asn1_x509::{RSAPrivateKey, RSAPublicKey}; +use tss_esapi::abstraction::transient::RsaExponent; use zeroize::Zeroize; -// Public exponent value for all RSA keys. -const PUBLIC_EXPONENT: [u8; 3] = [0x01, 0x00, 0x01]; const AUTH_VAL_LEN: usize = 32; // Inserts a new mapping in the Key Info manager that stores the PasswordContext. @@ -119,9 +119,10 @@ impl TpmProvider { ) -> Result { match op.attributes.key_type { Type::RsaPublicKey => self.psa_import_key_internal_rsa_public(app_name, op), + Type::RsaKeyPair => self.psa_import_key_internal_rsa_keypair(app_name, op), _ => { error!( - "The TPM provider does not support the {:?} key type.", + "The TPM provider does not support importing for the {:?} key type.", op.attributes.key_type ); Err(ResponseStatus::PsaErrorNotSupported) @@ -154,50 +155,9 @@ impl TpmProvider { ResponseStatus::PsaErrorInvalidArgument })?; - if public_key.modulus.is_negative() || public_key.public_exponent.is_negative() { - error!("Only positive modulus and public exponent are supported."); - return Err(ResponseStatus::PsaErrorInvalidArgument); - } + validate_public_key(&public_key, &attributes)?; - if public_key.public_exponent.as_unsigned_bytes_be() != PUBLIC_EXPONENT { - if crate::utils::GlobalConfig::log_error_details() { - error!("The TPM Provider only supports 0x101 as public exponent for RSA public keys, {:?} given.", public_key.public_exponent.as_unsigned_bytes_be()); - } else { - error!( - "The TPM Provider only supports 0x101 as public exponent for RSA public keys" - ); - } - return Err(ResponseStatus::PsaErrorNotSupported); - } let key_data = public_key.modulus.as_unsigned_bytes_be(); - let len = key_data.len(); - - let key_bits = attributes.bits; - if key_bits != 0 && len * 8 != key_bits { - if crate::utils::GlobalConfig::log_error_details() { - error!( - "`bits` field of key attributes (value: {}) must be either 0 or equal to the size of the key in `data` (value: {}).", - attributes.bits, - len * 8 - ); - } else { - error!("`bits` field of key attributes must be either 0 or equal to the size of the key in `data`."); - } - return Err(ResponseStatus::PsaErrorInvalidArgument); - } - - if len != 128 && len != 256 { - if crate::utils::GlobalConfig::log_error_details() { - error!( - "The TPM provider only supports 1024 and 2048 bits RSA public keys ({} bits given).", - len * 8 - ); - } else { - error!("The TPM provider only supports 1024 and 2048 bits RSA public keys"); - } - return Err(ResponseStatus::PsaErrorNotSupported); - } - let pub_key_context = esapi_context .load_external_rsa_public_key(&key_data) .map_err(|e| { @@ -218,6 +178,64 @@ impl TpmProvider { Ok(psa_import_key::Result {}) } + pub(super) fn psa_import_key_internal_rsa_keypair( + &self, + app_name: ApplicationName, + op: psa_import_key::Operation, + ) -> Result { + let key_name = op.key_name; + let attributes = op.attributes; + let key_triple = KeyTriple::new(app_name, ProviderID::Tpm, key_name); + let key_data = op.data; + + let mut store_handle = self + .key_info_store + .write() + .expect("Key store lock poisoned"); + let mut esapi_context = self + .esapi_context + .lock() + .expect("ESAPI Context lock poisoned"); + + let private_key: RSAPrivateKey = picky_asn1_der::from_bytes(key_data.expose_secret()) + .map_err(|err| { + format_error!("Could not deserialise key elements", err); + ResponseStatus::PsaErrorInvalidArgument + })?; + + // Derive the public key from the keypair. + let public_key = RSAPublicKey { + modulus: private_key.modulus.clone(), + public_exponent: private_key.public_exponent.clone(), + }; + + // Validate the public and the private key. + validate_public_key(&public_key, &attributes)?; + validate_private_key(&private_key, &attributes)?; + + let key_prime = private_key.prime_1.as_unsigned_bytes_be(); + let public_modulus = private_key.modulus.as_unsigned_bytes_be(); + + let keypair_context = esapi_context + .load_external_rsa(key_prime, public_modulus, RsaExponent::new(PUBLIC_EXPONENT)) + .map_err(|e| { + format_error!("Error creating a RSA signing key", e); + utils::to_response_status(e) + })?; + + insert_password_context( + &mut *store_handle, + key_triple, + PasswordContext { + context: keypair_context, + auth_value: Vec::new(), + }, + attributes, + )?; + + Ok(psa_import_key::Result {}) + } + pub(super) fn psa_export_public_key_internal( &self, app_name: ApplicationName, diff --git a/src/providers/tpm_provider/mod.rs b/src/providers/tpm_provider/mod.rs index 55acb259..e3eb43cd 100644 --- a/src/providers/tpm_provider/mod.rs +++ b/src/providers/tpm_provider/mod.rs @@ -301,7 +301,7 @@ impl TpmProviderBuilder { .with_root_key_auth_size(ROOT_KEY_AUTH_SIZE) .with_hierarchy_auth(hierarchy_auth) .with_hierarchy(tss_esapi::utils::Hierarchy::Owner) - .with_session_hash_alg(HashingAlgorithm::Sha256.into()) + .with_session_hash_alg(HashingAlgorithm::Sha256) .with_default_context_cipher(default_cipher) .build() .map_err(|e| { diff --git a/src/providers/tpm_provider/utils.rs b/src/providers/tpm_provider/utils.rs index 4e949894..604510ca 100644 --- a/src/providers/tpm_provider/utils.rs +++ b/src/providers/tpm_provider/utils.rs @@ -6,16 +6,19 @@ use parsec_interface::operations::psa_algorithm::*; use parsec_interface::operations::psa_key_attributes::*; use parsec_interface::requests::{ResponseStatus, Result}; use picky_asn1::wrapper::IntegerAsn1; -use picky_asn1_x509::RSAPublicKey; +use picky_asn1_x509::{RSAPrivateKey, RSAPublicKey}; use serde::{Deserialize, Serialize}; use std::convert::TryInto; use tss_esapi::abstraction::transient::KeyParams; use tss_esapi::constants::algorithm::{EllipticCurve, HashingAlgorithm}; use tss_esapi::constants::response_code::Tss2ResponseCodeKind; -use tss_esapi::utils::{AsymSchemeUnion, PublicKey, Signature, SignatureData, TpmsContext}; +use tss_esapi::utils::{ + AsymSchemeUnion, PublicKey, Signature, SignatureData, TpmsContext, RSA_KEY_SIZES, +}; use tss_esapi::Error; use zeroize::Zeroizing; -const PUBLIC_EXPONENT: [u8; 3] = [0x01, 0x00, 0x01]; +pub const PUBLIC_EXPONENT: u32 = 0x10001; +const PUBLIC_EXPONENT_BYTES: [u8; 3] = [0x01, 0x00, 0x01]; /// Convert the TSS library specific error values to ResponseStatus values that are returned on /// the wire protocol @@ -179,7 +182,7 @@ pub fn pub_key_to_bytes(pub_key: PublicKey, key_attributes: Attributes) -> Resul match pub_key { PublicKey::Rsa(key) => picky_asn1_der::to_vec(&RSAPublicKey { modulus: IntegerAsn1::from_bytes_be_unsigned(key), - public_exponent: IntegerAsn1::from_bytes_be_signed(PUBLIC_EXPONENT.to_vec()), + public_exponent: IntegerAsn1::from_bytes_be_signed(PUBLIC_EXPONENT_BYTES.to_vec()), }) .or(Err(ResponseStatus::PsaErrorGenericError)), PublicKey::Ecc { x, y } => { @@ -250,6 +253,99 @@ pub fn parsec_to_tpm_signature( }) } +/// Validates an RSAPublicKey against the attributes we expect. Returns ok on success, otherwise +/// returns an error. +pub fn validate_public_key(public_key: &RSAPublicKey, attributes: &Attributes) -> Result<()> { + if public_key.modulus.is_negative() || public_key.public_exponent.is_negative() { + error!("Only positive modulus and public exponent are supported."); + return Err(ResponseStatus::PsaErrorInvalidArgument); + } + + if public_key.public_exponent.as_unsigned_bytes_be() != PUBLIC_EXPONENT_BYTES { + if crate::utils::GlobalConfig::log_error_details() { + error!("The TPM Provider only supports 0x10001 as public exponent for RSA public keys, {:?} given.", public_key.public_exponent.as_unsigned_bytes_be()); + } else { + error!("The TPM Provider only supports 0x10001 as public exponent for RSA public keys"); + } + return Err(ResponseStatus::PsaErrorNotSupported); + } + let key_data = public_key.modulus.as_unsigned_bytes_be(); + let len = key_data.len(); + + let key_bits = attributes.bits; + if key_bits != 0 && len * 8 != key_bits { + if crate::utils::GlobalConfig::log_error_details() { + error!( + "`bits` field of key attributes (value: {}) must be either 0 or equal to the size of the key in `data` (value: {}).", + attributes.bits, + len * 8 + ); + } else { + error!("`bits` field of key attributes must be either 0 or equal to the size of the key in `data`."); + } + return Err(ResponseStatus::PsaErrorInvalidArgument); + } + + let valid_key_sizes_vec = RSA_KEY_SIZES.to_vec(); + if !valid_key_sizes_vec.contains(&((len * 8) as u16)) { + if crate::utils::GlobalConfig::log_error_details() { + error!( + "The TPM provider only supports RSA public keys of size {:?} bits ({} bits given).", + valid_key_sizes_vec, + len * 8, + ); + } else { + error!( + "The TPM provider only supports RSA public keys of size {:?} bits", + valid_key_sizes_vec, + ); + } + return Err(ResponseStatus::PsaErrorNotSupported); + } + + Ok(()) +} + +/// Validates an RSAPrivateKey against the attributes we expect. Returns ok on success, otherwise +/// returns an error. +pub fn validate_private_key(private_key: &RSAPrivateKey, attributes: &Attributes) -> Result<()> { + // NOTE: potentially incomplete, but any errors that aren't caught here should be caught + // further down the stack (i.e. in the tss crate). + + // The public exponent must be exactly 0x10001 -- that is the only value supported by the TPM + // provider. Reject everything else. + let given_public_exponent = private_key.public_exponent.as_unsigned_bytes_be(); + if given_public_exponent != PUBLIC_EXPONENT_BYTES { + if crate::utils::GlobalConfig::log_error_details() { + error!( + "Unexpected public exponent in private key (expected: {:?}, got: {:?}).", + PUBLIC_EXPONENT_BYTES, given_public_exponent + ); + } else { + error!("Unexpected public exponent in private key."); + } + return Err(ResponseStatus::PsaErrorInvalidArgument); + } + + // The key prime's length in bits should be exactly half of the size of the size of the key's + // public modulus. + let key_prime = private_key.prime_1.as_unsigned_bytes_be(); + let key_prime_len_bits = key_prime.len() * 8; + if key_prime_len_bits != attributes.bits / 2 { + if crate::utils::GlobalConfig::log_error_details() { + error!( + "The key prime is not of the expected size (expected {}, got {}).", + attributes.bits / 2, + key_prime_len_bits, + ); + } else { + error!("The key prime is not of the expected size.",); + } + return Err(ResponseStatus::PsaErrorInvalidArgument); + } + Ok(()) +} + fn bytes_to_signature_data( data: Zeroizing>, key_attributes: Attributes, From 8197ce9601377d71887e1b2d939e60210843abc4 Mon Sep 17 00:00:00 2001 From: Joe Ellis Date: Thu, 10 Sep 2020 11:31:04 +0100 Subject: [PATCH 4/4] Add test for importing RSA keypair with TPM provider Signed-off-by: Joe Ellis --- tests/providers/tpm.rs | 97 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/tests/providers/tpm.rs b/tests/providers/tpm.rs index 7049a0bd..26eb33e0 100644 --- a/tests/providers/tpm.rs +++ b/tests/providers/tpm.rs @@ -4,9 +4,11 @@ use lazy_static::lazy_static; use parsec_interface::operations::psa_algorithm::*; use parsec_interface::operations::psa_key_attributes::*; use parsec_interface::operations::{ - psa_asymmetric_decrypt, psa_export_public_key, psa_generate_key, psa_sign_hash, psa_verify_hash, + psa_asymmetric_decrypt, psa_export_public_key, psa_generate_key, psa_import_key, psa_sign_hash, + psa_verify_hash, }; use parsec_interface::requests::ResponseStatus; +use parsec_interface::secrecy::Secret; use parsec_service::authenticators::ApplicationName; use parsec_service::key_info_managers::on_disk_manager::OnDiskKeyInfoManagerBuilder; use parsec_service::providers::tpm_provider::{TpmProvider, TpmProviderBuilder}; @@ -132,6 +134,41 @@ fn gen_ecc_sign_key_op(key_name: String) -> psa_generate_key::Operation { } } +fn import_rsa_sign_keypair_op( + key_name: String, + key_size_bits: usize, + key_data: &[u8], +) -> psa_import_key::Operation { + psa_import_key::Operation { + key_name, + attributes: Attributes { + lifetime: Lifetime::Persistent, + key_type: Type::RsaKeyPair, + bits: key_size_bits, + policy: Policy { + usage_flags: UsageFlags { + export: true, + copy: false, + cache: false, + encrypt: false, + decrypt: false, + sign_message: true, + sign_hash: true, + verify_message: true, + verify_hash: true, + derive: false, + }, + permitted_algorithms: Algorithm::AsymmetricSignature( + AsymmetricSignature::RsaPkcs1v15Sign { + hash_alg: Hash::Sha256.into(), + }, + ), + }, + }, + data: Secret::new(key_data.to_vec()), + } +} + #[test] fn verify_with_ring() { let key_name = String::from("key_name"); @@ -284,3 +321,61 @@ fn asym_encrypt_with_crate() { assert_eq!(&initial_plaintext[..], &plaintext[..]); } + +#[test] +fn import_private_key() { + // This hex represents the private component of a 1024-bit private key. + const KEY_SIZE_BITS: usize = 1024; + const KEY_DATA: [u8; 609] = [ + 0x30, 0x82, 0x02, 0x5D, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xC7, 0xDF, 0x1D, 0x9B, + 0x29, 0xBA, 0x60, 0x1B, 0x1C, 0x65, 0x2C, 0xB8, 0xEF, 0x7F, 0x8E, 0x2C, 0x01, 0x8A, 0x9B, + 0xE9, 0x6B, 0xFC, 0x5D, 0xF6, 0x8D, 0x0F, 0x4E, 0x72, 0xC0, 0xD1, 0xB7, 0x65, 0xE6, 0x67, + 0x80, 0x98, 0x55, 0xFF, 0xF0, 0x15, 0x28, 0xCC, 0x19, 0x59, 0x92, 0xEC, 0x06, 0x34, 0x03, + 0x3B, 0x37, 0x0D, 0x3D, 0xF0, 0x10, 0xD2, 0x61, 0x74, 0x4D, 0xB9, 0x84, 0x64, 0x88, 0x4C, + 0x51, 0x71, 0x92, 0x3D, 0xD9, 0x2D, 0x20, 0x06, 0xE6, 0x53, 0x66, 0x47, 0x88, 0x2A, 0x70, + 0xB8, 0xD9, 0x2E, 0x71, 0x73, 0x06, 0x75, 0x61, 0x18, 0xF8, 0x1C, 0xB5, 0xA6, 0xE5, 0x9C, + 0x78, 0xF7, 0xFD, 0x7D, 0xCC, 0x85, 0x4A, 0xC9, 0x21, 0xE0, 0x4E, 0x3C, 0x8E, 0x4F, 0x00, + 0xDD, 0xD5, 0xA8, 0xAA, 0x0E, 0x79, 0x07, 0x24, 0x25, 0x60, 0x75, 0x12, 0x18, 0x60, 0x0A, + 0xD5, 0x07, 0xAE, 0x63, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x81, 0x00, 0x9E, 0xC9, + 0xD1, 0x19, 0x8E, 0x63, 0x35, 0x2B, 0x14, 0xBA, 0x04, 0x77, 0xC0, 0x3E, 0x14, 0x53, 0x3D, + 0xBE, 0x42, 0xF3, 0x85, 0x08, 0xF0, 0x15, 0x8A, 0x27, 0x98, 0xE9, 0x6D, 0xEA, 0xAE, 0xCB, + 0x53, 0xEA, 0xF2, 0xAD, 0x13, 0xD5, 0xCB, 0x84, 0xE3, 0xEE, 0x92, 0x4D, 0x29, 0x7E, 0x3D, + 0xC7, 0x60, 0xB1, 0xD0, 0xA0, 0xC2, 0x8E, 0x50, 0xAE, 0xF3, 0x21, 0x95, 0x06, 0x47, 0xFA, + 0x1E, 0x95, 0x29, 0x72, 0xB7, 0xED, 0x8D, 0x63, 0x61, 0x42, 0x45, 0x14, 0xD1, 0x8A, 0xD3, + 0x1A, 0xE0, 0xDC, 0x03, 0x02, 0xD7, 0x39, 0x4B, 0x42, 0x7F, 0x31, 0xAD, 0x4B, 0xD3, 0xE1, + 0x14, 0x42, 0xF6, 0x26, 0x48, 0xC4, 0x61, 0xE1, 0x69, 0x02, 0xD5, 0xCB, 0x83, 0x34, 0xDD, + 0xD5, 0x3D, 0x85, 0x48, 0x11, 0x95, 0x64, 0x30, 0x53, 0xA8, 0x2F, 0x8D, 0x35, 0xED, 0x6A, + 0xF8, 0x06, 0x7C, 0x94, 0x08, 0xC1, 0x02, 0x41, 0x00, 0xFD, 0x95, 0x7D, 0xCB, 0xBE, 0x88, + 0x4A, 0x8E, 0x4A, 0xDD, 0xEC, 0xBC, 0x5D, 0x9F, 0x4B, 0x97, 0xC9, 0x5D, 0x86, 0x3C, 0x98, + 0x84, 0xA0, 0x87, 0x9C, 0x91, 0x71, 0x54, 0x1F, 0x3F, 0xB0, 0x91, 0x81, 0x9B, 0x1D, 0xB2, + 0xD3, 0x4C, 0x79, 0x45, 0x59, 0x78, 0x80, 0x18, 0xE4, 0x68, 0x0F, 0xCE, 0xE6, 0x48, 0x42, + 0x24, 0x38, 0x5F, 0xC8, 0x7E, 0xEA, 0x70, 0xFF, 0x68, 0xA7, 0xE9, 0x0D, 0xB1, 0x02, 0x41, + 0x00, 0xC9, 0xC6, 0x9D, 0xB3, 0xEA, 0x14, 0xA3, 0xB9, 0x6B, 0x58, 0xE2, 0x9E, 0x40, 0x0A, + 0x99, 0x75, 0x05, 0xB6, 0x74, 0x8A, 0x08, 0x70, 0x34, 0x47, 0x9F, 0x4F, 0x6E, 0xDB, 0xFE, + 0x44, 0x43, 0xF4, 0x4C, 0xF7, 0x3B, 0x6A, 0x48, 0xD0, 0xAC, 0x6D, 0xCB, 0x83, 0x00, 0x2B, + 0x19, 0xC3, 0x57, 0xC7, 0x31, 0x0C, 0x12, 0xFE, 0x88, 0x0A, 0xEA, 0x04, 0x2A, 0x2F, 0xBE, + 0x66, 0x76, 0x95, 0x9E, 0x53, 0x02, 0x40, 0x0A, 0x3F, 0xF5, 0xA2, 0xBB, 0xA3, 0xD4, 0xA7, + 0xA5, 0xBD, 0x0C, 0xA9, 0x9C, 0x7B, 0x28, 0xDA, 0x0C, 0xC8, 0x9B, 0xF9, 0x6D, 0x0C, 0xC7, + 0x54, 0x53, 0xEE, 0xC9, 0x0E, 0xE6, 0x68, 0x73, 0xA1, 0x9E, 0x04, 0x80, 0x11, 0xCF, 0x5A, + 0xA2, 0xF8, 0x3B, 0xA2, 0x94, 0x42, 0xED, 0x50, 0x8B, 0x7B, 0x08, 0x71, 0xD9, 0x42, 0x8F, + 0x88, 0xC7, 0x98, 0xE1, 0xAF, 0x09, 0x93, 0xD8, 0x5D, 0xA2, 0x31, 0x02, 0x41, 0x00, 0xAD, + 0x13, 0x3F, 0xFC, 0xAE, 0x62, 0x0B, 0xDA, 0x25, 0x59, 0x35, 0xF1, 0xD6, 0x2F, 0x01, 0x58, + 0x9E, 0x90, 0xD5, 0xBF, 0xFC, 0xE2, 0xFA, 0x05, 0x21, 0x82, 0xCA, 0x2D, 0xCC, 0x19, 0x94, + 0x4C, 0x7E, 0xA4, 0x67, 0x03, 0x90, 0xF7, 0xE5, 0x9F, 0xBC, 0x3C, 0x5F, 0x2D, 0x99, 0x48, + 0xB5, 0x07, 0x78, 0x6B, 0xC9, 0xF3, 0x28, 0x90, 0x6C, 0x11, 0x2C, 0x7A, 0x8D, 0x90, 0x68, + 0x51, 0x88, 0x5F, 0x02, 0x40, 0x5F, 0x9D, 0x31, 0x1B, 0x32, 0x65, 0xF1, 0x50, 0x7B, 0x7E, + 0x10, 0xDA, 0x8D, 0x2A, 0xF0, 0xAE, 0x39, 0x14, 0xE1, 0xC8, 0xE4, 0x24, 0xC6, 0x04, 0x08, + 0x46, 0x68, 0xDC, 0xD8, 0x53, 0x65, 0x02, 0x27, 0x28, 0xDD, 0x9F, 0xB2, 0x8A, 0x8E, 0x94, + 0xF6, 0x3E, 0x6E, 0xFF, 0x5D, 0xB8, 0x4B, 0xAC, 0x25, 0x75, 0x5F, 0x99, 0x09, 0x56, 0xB0, + 0xF7, 0x38, 0x18, 0x62, 0xDA, 0x0B, 0xD0, 0x0A, 0x27, + ]; + + let key_name = String::from("key_name"); + let app_name = ApplicationName::new(String::from("import_private_key")); + let _ = TPM_PROVIDER + .psa_import_key( + app_name, + import_rsa_sign_keypair_op(key_name, KEY_SIZE_BITS, &KEY_DATA), + ) + .unwrap(); +}