Skip to content

Activate credential #558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ log = { version = "0.4.14", features = ["serde"] }
cryptoki = { version = "0.2.0", optional = true, features = ["psa-crypto-conversions"] }
picky-asn1-der = { version = "<=0.2.4", optional = true }
picky-asn1 = { version = ">=0.3.1, <=0.3.1", optional = true }
tss-esapi = { git = "https://github.com/parallaxsecond/rust-tss-esapi.git", revision = "714fe81e4a9b1964b878dee9ed5e974d6891092e", optional = true }
tss-esapi = { git = "https://github.com/parallaxsecond/rust-tss-esapi.git", rev = "62fb9b7b05b1e607518ae127406f3b85991205b9", optional = true }
bincode = "1.3.1"
structopt = "0.3.21"
derivative = "2.2.0"
Expand Down
11 changes: 11 additions & 0 deletions ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ cleanup () {
stop_service
# Stop tpm_server if running
if [ -n "$TPM_SRV_PID" ]; then kill $TPM_SRV_PID || true; fi
if [ -n "$TPM_MC_SRV_PID" ]; then kill $TPM_MC_SRV_PID || true; fi
# Remove the slot_number line added earlier
find e2e_tests -name "*toml" -not -name "Cargo.toml" -exec sed -i 's/^slot_number =.*/# slot_number/' {} \;
# Remove fake mapping and temp files
Expand Down Expand Up @@ -163,6 +164,16 @@ if [ "$PROVIDER_NAME" = "tpm" ] || [ "$PROVIDER_NAME" = "all" ] || [ "$PROVIDER_
# The -c flag is not used because some keys were created in the TPM via the generate-keys.sh
# script. Ownership has already been taken with "tpm_pass".
tpm2_startup -T mssim

# Start and configure TPM server for MakeCredential
TPM_MC_PORT=4321
mkdir -p /tmp/mc_tpm
pushd /tmp/mc_tpm
tpm_server -port $TPM_MC_PORT &
TPM_MC_SRV_PID=$!
sleep 5
tpm2_startup -c -T mssim:port=$TPM_MC_PORT
popd
fi

if [ "$PROVIDER_NAME" = "pkcs11" ] || [ "$PROVIDER_NAME" = "all" ] || [ "$PROVIDER_NAME" = "coverage" ]; then
Expand Down
8 changes: 8 additions & 0 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ key_info_manager = "on-disk-manager"
# e.g. "str:password", or to represent a string version of a hex value, e.g. "hex:1a2b3c". If no prefix is
# provided, the value is considered to be a string.
#owner_hierarchy_auth = "password"
# (Optional) Authentication value for performing operations on the TPM Endorsement Hierarchy. The string can
# be empty, however we strongly suggest that you use a secure passcode.
# This authentication value is used for operations that rely on keys stored in the Endorsement Hierarchy, e.g.
# key attestation using the default Endorsement Key.
# To align with TPM tooling, PARSEC allows "endorsement_hierarchy_auth" to have a prefix indicating a string value,
# e.g. "str:password", or to represent a string version of a hex value, e.g. "hex:1a2b3c". If no prefix is
# provided, the value is considered to be a string.
#endorsement_hierarchy_auth = "password"
# (Optional) Allows the service to still start without this provider if there is no TPM on the system. The priority list of providers will be as if this provider was commented out.
#skip_if_no_tpm = false

Expand Down
3 changes: 2 additions & 1 deletion e2e_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ publish = false

[dependencies]
serde = { version = "1.0.123", features = ["derive"] }
parsec-client = { git = "https://github.com/parallaxsecond/parsec-client-rust", rev = "9e7dd111e77afa9168c1bff84963125057568b6f", features = ["testing", "spiffe-auth"] }
parsec-client = { git = "https://github.com/parallaxsecond/parsec-client-rust", rev = "119664eac501c7f1d207f03905311a0634db13a6", features = ["testing", "spiffe-auth"] }
log = "0.4.14"
# Compatible version with crate rsa
rand = "0.7.3"
Expand All @@ -27,6 +27,7 @@ num_cpus = "1.13.0"
picky-asn1-der = "0.2.4"
picky-asn1 = "0.3.1"
sha2 = "0.9.3"
tss-esapi = { git = "https://github.com/parallaxsecond/rust-tss-esapi.git", rev = "62fb9b7b05b1e607518ae127406f3b85991205b9" }

[features]
mbed-crypto-provider = []
Expand Down
1 change: 1 addition & 0 deletions e2e_tests/docker_image/generate-keys.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sleep 5
tpm2_startup -c -T mssim
sleep 2
tpm2_changeauth -c owner tpm_pass -T mssim
tpm2_changeauth -c endorsement endorsement_pass -T mssim
cd /tmp/create_keys/parsec/e2e_tests
SLOT_NUMBER=`softhsm2-util --show-slots | head -n2 | tail -n1 | cut -d " " -f 2`
find . -name "*toml" -not -name "Cargo.toml" -exec sed -i "s/^# slot_number.*$/slot_number = $SLOT_NUMBER/" {} \;
Expand Down
1 change: 1 addition & 0 deletions e2e_tests/provider_cfg/tpm/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ provider_type = "Tpm"
key_info_manager = "on-disk-manager"
tcti = "mssim:host=127.0.0.1,port=2321"
owner_hierarchy_auth = "hex:74706d5f70617373" # "tpm_pass" in hex
endorsement_hierarchy_auth = "str:endorsement_pass"
21 changes: 21 additions & 0 deletions e2e_tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod stress;

pub use raw_request::RawRequestClient;

pub use parsec_client;
pub use parsec_client::core::request_client::RequestClient;
pub use parsec_client::error;

Expand Down Expand Up @@ -805,6 +806,26 @@ impl TestClient {
.can_do_crypto(check_type, attributes)
.map_err(convert_error)
}

pub fn prepare_activate_credential(
&self,
key_name: String,
) -> Result<parsec_client::core::basic_client::PrepareActivateCredential> {
self.basic_client
.prepare_activate_credential(key_name, None)
.map_err(convert_error)
}

pub fn activate_credential(
&self,
key_name: String,
credential: Vec<u8>,
secret: Vec<u8>,
) -> Result<Vec<u8>> {
self.basic_client
.activate_credential_attestation(key_name, None, credential, secret)
.map_err(convert_error)
}
}

impl Default for TestClient {
Expand Down
103 changes: 103 additions & 0 deletions e2e_tests/tests/per_provider/normal_tests/key_attestation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
#![cfg(feature = "tpm-provider")]
use e2e_tests::auto_test_keyname;
use e2e_tests::parsec_client::core::basic_client::PrepareActivateCredential;
use e2e_tests::TestClient;
use parsec_client::core::interface::requests::Opcode;
use std::{
convert::{TryFrom, TryInto},
env,
str::FromStr,
};
use tss_esapi::{
abstraction::ek,
abstraction::transient::MakeCredParams,
interface_types::{algorithm::AsymmetricAlgorithm, resource_handles::Hierarchy},
structures::{Public, PublicKeyRsa},
tcti_ldr::{NetworkTPMConfig, TctiNameConf},
utils::PublicKey,
Context,
};

const DEFAULT_HELPER_TPM_CONF: &str = "port=4321";
const CREDENTIAL: [u8; 16] = [0x11; 16];

fn create_tcti() -> TctiNameConf {
match env::var("TEST_TCTI") {
Err(_) => TctiNameConf::Mssim(
NetworkTPMConfig::from_str(DEFAULT_HELPER_TPM_CONF)
.expect("Failed to parse default TPM config"),
),
Ok(tctistr) => TctiNameConf::from_str(&tctistr).expect("Error parsing TEST_TCTI"),
}
}

fn make_credential(prep_activ_cred: PrepareActivateCredential) -> (Vec<u8>, Vec<u8>) {
let make_cred_params = MakeCredParams {
name: prep_activ_cred.name,
public: prep_activ_cred.public,
attesting_key_pub: PublicKey::Rsa(prep_activ_cred.attesting_key_pub),
};
let mut basic_ctx = Context::new(create_tcti()).expect("Failed to start TPM context");
// the public part of the EK is used, so we retrieve the parameters
let key_pub =
ek::create_ek_public_from_default_template(AsymmetricAlgorithm::Rsa, None).unwrap();
let key_pub = if let Public::Rsa {
object_attributes,
name_hashing_algorithm,
auth_policy,
parameters,
..
} = key_pub
{
Public::Rsa {
object_attributes,
name_hashing_algorithm,
auth_policy,
parameters,
unique: if let PublicKey::Rsa(val) = make_cred_params.attesting_key_pub {
PublicKeyRsa::try_from(val).unwrap()
} else {
panic!("Wrong public key type");
},
}
} else {
panic!("Wrong Public type");
};
let pub_handle = basic_ctx
.load_external_public(&key_pub, Hierarchy::Owner)
.unwrap();

let (cred, secret) = basic_ctx
.make_credential(
pub_handle,
CREDENTIAL.to_vec().try_into().unwrap(),
make_cred_params.name.to_vec().try_into().unwrap(),
)
.unwrap();
(cred.value().to_vec(), secret.value().to_vec())
}

#[test]
fn activate_credential() {
let key_name = auto_test_keyname!();
let mut client = TestClient::new();
if !client.is_operation_supported(Opcode::PrepareKeyAttestation) {
return;
}
client
.generate_rsa_sign_key(key_name.clone())
.expect("Failed to generate key");
let prep_activ_cred = client
.prepare_activate_credential(key_name.clone())
.expect("Failed to get parameters for MakeCredential");

let (cred, secret) = make_credential(prep_activ_cred);

let cred_out = client
.activate_credential(key_name, cred, secret)
.expect("Failed to activate credential");

assert_eq!(cred_out, CREDENTIAL.to_vec());
}
1 change: 1 addition & 0 deletions e2e_tests/tests/per_provider/normal_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ mod generate_random;
mod hash;
mod import_key;
mod key_agreement;
mod key_attestation;
mod key_attributes;
mod ping;
15 changes: 15 additions & 0 deletions src/back/backend_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,21 @@ impl BackEndHandler {
trace!("can_do_crypto egress");
self.result_to_response(NativeResult::CanDoCrypto(result), header)
}
NativeOperation::PrepareKeyAttestation(op_prepare_key_attestation) => {
let app = unwrap_or_else_return!(app.ok_or(ResponseStatus::NotAuthenticated));
let result = unwrap_or_else_return!(self
.provider
.prepare_key_attestation(app.into(), op_prepare_key_attestation));
trace!("prepare_key_attestation egress");
self.result_to_response(NativeResult::PrepareKeyAttestation(result), header)
}
NativeOperation::AttestKey(op_attest_key) => {
let app = unwrap_or_else_return!(app.ok_or(ResponseStatus::NotAuthenticated));
let result =
unwrap_or_else_return!(self.provider.attest_key(app.into(), op_attest_key));
trace!("attest_key egress");
self.result_to_response(NativeResult::AttestKey(result), header)
}
_ => {
// This default arm should be removed
// when all operation defind in Parsec-interface are implemented in the match.
Expand Down
31 changes: 26 additions & 5 deletions src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ pub mod trusted_service;

use crate::authenticators::ApplicationName;
use parsec_interface::operations::{
can_do_crypto, delete_client, list_authenticators, list_clients, list_keys, list_opcodes,
list_providers, ping, psa_aead_decrypt, psa_aead_encrypt, psa_asymmetric_decrypt,
psa_asymmetric_encrypt, psa_destroy_key, psa_export_key, psa_export_public_key,
psa_generate_key, psa_generate_random, psa_hash_compare, psa_hash_compute, psa_import_key,
psa_raw_key_agreement, psa_sign_hash, psa_sign_message, psa_verify_hash, psa_verify_message,
attest_key, can_do_crypto, delete_client, list_authenticators, list_clients, list_keys,
list_opcodes, list_providers, ping, prepare_key_attestation, psa_aead_decrypt,
psa_aead_encrypt, psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_destroy_key,
psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random, psa_hash_compare,
psa_hash_compute, psa_import_key, psa_raw_key_agreement, psa_sign_hash, psa_sign_message,
psa_verify_hash, psa_verify_message,
};
use parsec_interface::requests::{ResponseStatus, Result};

Expand Down Expand Up @@ -308,4 +309,24 @@ pub trait Provide {
trace!("can_do_crypto main ingress");
Err(ResponseStatus::PsaErrorNotSupported)
}

/// Prepare a key attestation operation.
fn prepare_key_attestation(
&self,
_app_name: ApplicationName,
_op: prepare_key_attestation::Operation,
) -> Result<prepare_key_attestation::Result> {
trace!("prepare_key_attestation ingress");
Err(ResponseStatus::PsaErrorNotSupported)
}

/// Attest a key.
fn attest_key(
&self,
_app_name: ApplicationName,
_op: attest_key::Operation,
) -> Result<attest_key::Result> {
trace!("attest_key ingress");
Err(ResponseStatus::PsaErrorNotSupported)
}
}
Loading