Skip to content

Commit

Permalink
Handle Provisioning Certification Keys (PCKs) (#1051)
Browse files Browse the repository at this point in the history
* Add PCK to server info

* Add PCK to chainspec

* Update chainspec genesis config to include PCKs for all TSSs

* Add sp-runtime to wasm deps of entropy-shared

* Bump tdx-quote, check PCK signature when verifying quotes

* Update benchmarks

* When mocking, derive PCK from TSS account id

* Get boundedvec from sp-core, not sp-runtime

* Ignore BoundedVec type when compiling for wasm with std

* Update propagation pallet mock

* Update attestation pallet mock

* Add helpers for deriving mock pcks

* Add actual PCK values to chainspec

* Rm unused import

* Update registry tests

* Update metadata

* Comments

* Fix client test

* Add random secret PCK to attestation pallet benchmark test

* Fix attestation benchmark

* Fix attestation benchmark again

* Update attestation pallet test

* Fix attestation pallet mock/bench

* Fix entropy-client test

* Fix client test

* Fix client test

* Changelog

* Rm unused dependency from staking pallet
  • Loading branch information
ameba23 authored Sep 25, 2024
1 parent 9de0a79 commit f286071
Show file tree
Hide file tree
Showing 26 changed files with 304 additions and 95 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ At the moment this project **does not** adhere to
- Add remove program function to entropy-client ([#1023](https://github.com/entropyxyz/entropy-core/pull/1023))
- Select validators for jumpstart DKG [#1053](https://github.com/entropyxyz/entropy-core/pull/1053))
- Add a programs version ([#1045](https://github.com/entropyxyz/entropy-core/pull/1045))
- Handle Provisioning Certification Keys (PCKs) ([#1051](https://github.com/entropyxyz/entropy-core/pull/1051))

### Changed
- Fix TSS `AccountId` keys in chainspec ([#993](https://github.com/entropyxyz/entropy-core/pull/993))
Expand Down
4 changes: 3 additions & 1 deletion Cargo.lock

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

Binary file modified crates/client/entropy_metadata.scale
Binary file not shown.
16 changes: 13 additions & 3 deletions crates/client/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ use crate::{
update_programs,
};
use entropy_testing_utils::{
constants::TEST_PROGRAM_WASM_BYTECODE, jump_start_network,
substrate_context::test_context_stationary, test_node_process_testing_state,
constants::{TEST_PROGRAM_WASM_BYTECODE, TSS_ACCOUNTS},
helpers::{derive_mock_pck_verifying_key, encode_verifying_key},
jump_start_network,
substrate_context::test_context_stationary,
test_node_process_testing_state,
};
use serial_test::serial;
use sp_core::{sr25519, Pair, H256};
Expand Down Expand Up @@ -64,6 +67,12 @@ async fn test_change_threshold_accounts() {
)
.await
.unwrap();

let provisioning_certification_key = {
let key = derive_mock_pck_verifying_key(&TSS_ACCOUNTS[0]);
BoundedVec(encode_verifying_key(&key).unwrap().to_vec())
};

assert_eq!(
format!("{:?}", result),
format!(
Expand All @@ -73,7 +82,8 @@ async fn test_change_threshold_accounts() {
ServerInfo {
tss_account: AccountId32(one.pair().public().0),
x25519_public_key,
endpoint: "127.0.0.1:3001".as_bytes().to_vec()
endpoint: "127.0.0.1:3001".as_bytes().to_vec(),
provisioning_certification_key,
}
)
)
Expand Down
4 changes: 4 additions & 0 deletions crates/shared/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ pub enum HashingAlgorithm {
/// A compressed, serialized [synedrion::ecdsa::VerifyingKey<k256::Secp256k1>]
pub type EncodedVerifyingKey = [u8; VERIFICATION_KEY_LENGTH as usize];

#[cfg(not(feature = "wasm"))]
pub type BoundedVecEncodedVerifyingKey =
sp_runtime::BoundedVec<u8, sp_runtime::traits::ConstU32<VERIFICATION_KEY_LENGTH>>;

/// Input data to be included in a TDX attestation
pub struct QuoteInputData(pub [u8; 64]);

Expand Down
1 change: 1 addition & 0 deletions crates/testing-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="1d210d1
hex ="0.4.3"
rand_core ="0.6.4"
rand ="0.8.5"
tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote", rev="cb167f2", features=["mock"] }

# Logging
tracing ="0.1.37"
Expand Down
19 changes: 18 additions & 1 deletion crates/testing-utils/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use crate::{
ChainSpecType,
};
use entropy_protocol::PartyId;
use subxt::{backend::legacy::LegacyRpcMethods, OnlineClient};
use rand::{rngs::StdRng, SeedableRng};
use subxt::{backend::legacy::LegacyRpcMethods, utils::AccountId32, OnlineClient};
pub use tdx_quote::encode_verifying_key;

/// A helper for setting up tests which starts both a set of TS servers and a chain node and returns
/// the chain API as well as IP addresses and PartyId of the started validators
Expand Down Expand Up @@ -52,3 +54,18 @@ pub async fn spawn_tss_nodes_and_start_chain(
};
(api, rpc, validator_ips, validator_ids)
}

/// Get the mock PCK that will be used for a given TSS account ID
pub fn derive_mock_pck_verifying_key(tss_account_id: &AccountId32) -> tdx_quote::VerifyingKey {
let mut pck_seeder = StdRng::from_seed(tss_account_id.0);
let pck = tdx_quote::SigningKey::random(&mut pck_seeder);
tdx_quote::VerifyingKey::from(pck)
}

/// For each test TSS account, display the encoded mock PCK
pub fn print_test_pck_verifying_keys() {
for tss_account in crate::constants::TSS_ACCOUNTS.iter() {
let pck = derive_mock_pck_verifying_key(tss_account);
println!("{:?}", encode_verifying_key(&pck));
}
}
5 changes: 3 additions & 2 deletions crates/threshold-signature-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ thiserror ="1.0.64"
blake2 ="0.10.4"
x25519-dalek ={ version="2.0.1", features=["static_secrets"] }
rand_core ="0.6.4"
rand ="0.8.5"
zeroize ="1.8.1"
hex ="0.4.3"
reqwest-eventsource="0.6"
Expand Down Expand Up @@ -71,7 +72,7 @@ sha1="0.10.6"
sha2="0.10.8"
hkdf="0.12.4"
project-root={ version="0.2.2", optional=true }
tdx-quote={ git="https://github.com/entropyxyz/tdx-quote", rev="f7968ff", optional=true, features=[
tdx-quote={ git="https://github.com/entropyxyz/tdx-quote", rev="cb167f2", optional=true, features=[
"mock",
] }
configfs-tsm={ git="https://github.com/entropyxyz/configfs-tsm", rev="f32c166", optional=true }
Expand All @@ -88,7 +89,7 @@ ethers-core ="2.0.14"
schnorrkel ={ version="0.11.4", default-features=false, features=["std"] }
schemars ={ version="0.8.21" }
subxt-signer="0.35.3"
tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote", rev="f7968ff", features=["mock"] }
tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote", rev="cb167f2", features=["mock"] }

# Note: We don't specify versions here because otherwise we run into a cyclical dependency between
# `entropy-tss` and `entropy-testing-utils` when we try and publish the `entropy-tss` crate.
Expand Down
9 changes: 7 additions & 2 deletions crates/threshold-signature-server/src/attestation/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ pub async fn create_quote(
signer: &PairSigner<EntropyConfig, sp_core::sr25519::Pair>,
x25519_secret: &StaticSecret,
) -> Result<Vec<u8>, AttestationErr> {
use rand::{rngs::StdRng, SeedableRng};
use rand_core::OsRng;
use sp_core::Pair;

// In the real thing this is the hardware key used in the quoting enclave
// In the real thing this is the key used in the quoting enclave
let signing_key = tdx_quote::SigningKey::random(&mut OsRng);

let public_key = x25519_dalek::PublicKey::from(x25519_secret);
Expand All @@ -93,7 +94,11 @@ pub async fn create_quote(
block_number,
);

let quote = tdx_quote::Quote::mock(signing_key.clone(), input_data.0).as_bytes().to_vec();
// This is generated deterministically from TSS account id
let mut pck_seeder = StdRng::from_seed(signer.signer().public().0);
let pck = tdx_quote::SigningKey::random(&mut pck_seeder);

let quote = tdx_quote::Quote::mock(signing_key.clone(), pck, input_data.0).as_bytes().to_vec();
Ok(quote)
}

Expand Down
33 changes: 24 additions & 9 deletions node/cli/src/chain_spec/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::chain_spec::{get_account_id_from_seed, ChainSpec};
use crate::chain_spec::{get_account_id_from_seed, provisioning_certification_key, ChainSpec};
use crate::endowed_accounts::endowed_accounts_dev;

use entropy_runtime::{
Expand All @@ -24,9 +24,9 @@ use entropy_runtime::{
};
use entropy_runtime::{AccountId, Balance};
use entropy_shared::{
X25519PublicKey as TssX25519PublicKey, DEVICE_KEY_AUX_DATA_TYPE, DEVICE_KEY_CONFIG_TYPE,
DEVICE_KEY_HASH, DEVICE_KEY_PROXY, INITIAL_MAX_INSTRUCTIONS_PER_PROGRAM, SIGNER_THRESHOLD,
TOTAL_SIGNERS,
BoundedVecEncodedVerifyingKey, X25519PublicKey as TssX25519PublicKey, DEVICE_KEY_AUX_DATA_TYPE,
DEVICE_KEY_CONFIG_TYPE, DEVICE_KEY_HASH, DEVICE_KEY_PROXY,
INITIAL_MAX_INSTRUCTIONS_PER_PROGRAM, SIGNER_THRESHOLD, TOTAL_SIGNERS,
};
use grandpa_primitives::AuthorityId as GrandpaId;
use itertools::Itertools;
Expand All @@ -38,75 +38,85 @@ use sp_core::{sr25519, ByteArray};
use sp_runtime::{BoundedVec, Perbill};

pub fn devnet_three_node_initial_tss_servers(
) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String)> {
) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String, BoundedVecEncodedVerifyingKey)> {
let alice = (
crate::chain_spec::tss_account_id::ALICE.clone(),
crate::chain_spec::tss_x25519_public_key::ALICE,
"127.0.0.1:3001".to_string(),
provisioning_certification_key::ALICE.clone(),
);

let bob = (
crate::chain_spec::tss_account_id::BOB.clone(),
crate::chain_spec::tss_x25519_public_key::BOB,
"127.0.0.1:3002".to_string(),
provisioning_certification_key::BOB.clone(),
);

let charlie = (
crate::chain_spec::tss_account_id::CHARLIE.clone(),
crate::chain_spec::tss_x25519_public_key::CHARLIE,
"127.0.0.1:3003".to_string(),
provisioning_certification_key::CHARLIE.clone(),
);

vec![alice, bob, charlie]
}

pub fn devnet_local_docker_three_node_initial_tss_servers(
) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String)> {
) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String, BoundedVecEncodedVerifyingKey)> {
let alice = (
crate::chain_spec::tss_account_id::ALICE.clone(),
crate::chain_spec::tss_x25519_public_key::ALICE,
"alice-tss-server:3001".to_string(),
provisioning_certification_key::ALICE.clone(),
);

let bob = (
crate::chain_spec::tss_account_id::BOB.clone(),
crate::chain_spec::tss_x25519_public_key::BOB,
"bob-tss-server:3002".to_string(),
provisioning_certification_key::BOB.clone(),
);

let charlie = (
crate::chain_spec::tss_account_id::CHARLIE.clone(),
crate::chain_spec::tss_x25519_public_key::CHARLIE,
"charlie-tss-server:3003".to_string(),
provisioning_certification_key::CHARLIE.clone(),
);

vec![alice, bob, charlie]
}

pub fn devnet_local_docker_four_node_initial_tss_servers(
) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String)> {
) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String, BoundedVecEncodedVerifyingKey)> {
let alice = (
crate::chain_spec::tss_account_id::ALICE.clone(),
crate::chain_spec::tss_x25519_public_key::ALICE,
"alice-tss-server:3001".to_string(),
provisioning_certification_key::ALICE.clone(),
);

let bob = (
crate::chain_spec::tss_account_id::BOB.clone(),
crate::chain_spec::tss_x25519_public_key::BOB,
"bob-tss-server:3002".to_string(),
provisioning_certification_key::BOB.clone(),
);

let dave = (
crate::chain_spec::tss_account_id::DAVE.clone(),
crate::chain_spec::tss_x25519_public_key::DAVE,
"dave-tss-server:3003".to_string(),
provisioning_certification_key::DAVE.clone(),
);

let eve = (
crate::chain_spec::tss_account_id::EVE.clone(),
crate::chain_spec::tss_x25519_public_key::EVE_TSS,
"eve-tss-server:3004".to_string(),
provisioning_certification_key::EVE.clone(),
);

vec![alice, bob, dave, eve]
Expand Down Expand Up @@ -194,7 +204,12 @@ pub fn development_genesis_config(
)>,
initial_nominators: Vec<AccountId>,
root_key: AccountId,
initial_tss_servers: Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String)>,
initial_tss_servers: Vec<(
sp_runtime::AccountId32,
TssX25519PublicKey,
String,
BoundedVecEncodedVerifyingKey,
)>,
) -> serde_json::Value {
// Note that any endowed_accounts added here will be included in the `elections` and
// `technical_committee` genesis configs. If you don't want that, don't push those accounts to
Expand Down Expand Up @@ -272,7 +287,7 @@ pub fn development_genesis_config(
.iter()
.zip(initial_tss_servers.iter())
.map(|(auth, tss)| {
(auth.0.clone(), (tss.0.clone(), tss.1, tss.2.as_bytes().to_vec()))
(auth.0.clone(), (tss.0.clone(), tss.1, tss.2.as_bytes().to_vec(), tss.3.clone()))
})
.collect::<Vec<_>>(),
proactive_refresh_data: (vec![], vec![]),
Expand Down
6 changes: 5 additions & 1 deletion node/cli/src/chain_spec/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::chain_spec::{get_account_id_from_seed, ChainSpec};
use crate::chain_spec::{get_account_id_from_seed, provisioning_certification_key, ChainSpec};
use crate::endowed_accounts::endowed_accounts_dev;

use entropy_runtime::{
Expand Down Expand Up @@ -158,6 +158,7 @@ pub fn integration_tests_genesis_config(
crate::chain_spec::tss_account_id::ALICE.clone(),
crate::chain_spec::tss_x25519_public_key::ALICE,
"127.0.0.1:3001".as_bytes().to_vec(),
provisioning_certification_key::ALICE.clone(),
),
),
(
Expand All @@ -166,6 +167,7 @@ pub fn integration_tests_genesis_config(
crate::chain_spec::tss_account_id::BOB.clone(),
crate::chain_spec::tss_x25519_public_key::BOB,
"127.0.0.1:3002".as_bytes().to_vec(),
provisioning_certification_key::BOB.clone(),
),
),
(
Expand All @@ -174,6 +176,7 @@ pub fn integration_tests_genesis_config(
crate::chain_spec::tss_account_id::CHARLIE.clone(),
crate::chain_spec::tss_x25519_public_key::CHARLIE,
"127.0.0.1:3003".as_bytes().to_vec(),
provisioning_certification_key::CHARLIE.clone(),
),
),
(
Expand All @@ -182,6 +185,7 @@ pub fn integration_tests_genesis_config(
crate::chain_spec::tss_account_id::DAVE.clone(),
crate::chain_spec::tss_x25519_public_key::DAVE,
"127.0.0.1:3004".as_bytes().to_vec(),
provisioning_certification_key::DAVE.clone(),
),
),
],
Expand Down
29 changes: 29 additions & 0 deletions node/cli/src/chain_spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,35 @@ pub mod tss_x25519_public_key {
];
}

/// Mock provisioning certification keys for attestation of the test TS servers.
/// These are generated deterministically from their TSS account IDs using the helper function
/// entropy_testing_utils::helpers::print_test_pck_verifying_keys
pub mod provisioning_certification_key {
use entropy_shared::BoundedVecEncodedVerifyingKey;

lazy_static::lazy_static! {
pub static ref ALICE: BoundedVecEncodedVerifyingKey = vec![
2, 137, 55, 65, 52, 103, 166, 204, 247, 160, 46, 220, 5, 113, 151, 217, 157, 196, 11,
240, 175, 82, 148, 230, 31, 245, 207, 194, 3, 74, 121, 184, 20
].try_into().unwrap();
pub static ref BOB: BoundedVecEncodedVerifyingKey = vec![
3, 83, 163, 234, 166, 114, 67, 146, 122, 122, 99, 236, 205, 116, 209, 45, 230, 107, 62,
55, 147, 38, 185, 203, 157, 147, 156, 173, 233, 58, 134, 162, 156].try_into().unwrap();
pub static ref CHARLIE: BoundedVecEncodedVerifyingKey = vec![
2, 167, 50, 42, 76, 239, 190, 42, 72, 64, 110, 90, 172, 253, 252, 148, 115, 107, 34, 110,
2, 112, 184, 147, 87, 71, 63, 217, 238, 89, 253, 97, 176
].try_into().unwrap();
pub static ref DAVE: BoundedVecEncodedVerifyingKey = vec![
3, 68, 52, 130, 44, 84, 174, 32, 55, 213, 192, 7, 121, 188, 19, 231, 134, 47, 223, 166,
199, 118, 161, 203, 142, 75, 184, 108, 165, 70, 251, 249, 142
].try_into().unwrap();
pub static ref EVE: BoundedVecEncodedVerifyingKey = vec![
2, 60, 115, 185, 180, 118, 177, 23, 3, 49, 65, 92, 230, 60, 245, 1, 140, 149, 117, 238,
83, 69, 110, 30, 140, 31, 60, 69, 38, 34, 202, 242, 125
].try_into().unwrap();
}
}

fn entropy_properties() -> Properties {
json!({"tokenDecimals": 10, "tokenSymbol": "BITS" }).as_object().unwrap().clone()
}
Expand Down
Loading

0 comments on commit f286071

Please sign in to comment.