Skip to content

Commit

Permalink
[tls-ra] provision light-client state too
Browse files Browse the repository at this point in the history
  • Loading branch information
clangenb committed Jul 31, 2023
1 parent 500955b commit 33db450
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 41 deletions.
2 changes: 1 addition & 1 deletion core/parentchain/light-client/src/concurrent_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ where
Validator: ValidatorTrait<ParentchainBlock>
+ LightClientState<ParentchainBlock>
+ ExtrinsicSenderTrait,
Seal: LightClientSealing<LightValidationState<ParentchainBlock>>,
Seal: LightClientSealing<LightClientState = LightValidationState<ParentchainBlock>>,
ParentchainBlock: ParentchainBlockTrait,
NumberFor<ParentchainBlock>: BlockNumberOps,
{
Expand Down
12 changes: 8 additions & 4 deletions core/parentchain/light-client/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ impl<B, L> LightClientStateSeal<B, L> {
}
}

impl<B: Block, LightClientState: Decode + Encode + Debug> LightClientSealing<LightClientState>
impl<B: Block, LightClientState: Decode + Encode + Debug> LightClientSealing
for LightClientStateSeal<B, LightClientState>
{
type LightClientState = LightClientState;

fn seal(&self, unsealed: &LightClientState) -> Result<()> {
trace!("Backup light client state");

Expand Down Expand Up @@ -128,9 +130,11 @@ impl<B, LightClientState> LightClientStateSealSync<B, LightClientState> {
}
}

impl<B: Block, LightClientState: Decode + Encode + Debug> LightClientSealing<LightClientState>
impl<B: Block, LightClientState: Decode + Encode + Debug> LightClientSealing
for LightClientStateSealSync<B, LightClientState>
{
type LightClientState = LightClientState;

fn seal(&self, unsealed: &LightClientState) -> Result<()> {
let _lock = self._rw_lock.write().map_err(|_| Error::PoisonedLock)?;
self.seal.seal(unsealed)
Expand Down Expand Up @@ -161,7 +165,7 @@ where
B: Block,
NumberFor<B>: finality_grandpa::BlockNumberOps,
OCallApi: EnclaveOnChainOCallApi,
LightClientSeal: LightClientSealing<LightValidationState<B>>,
LightClientSeal: LightClientSealing<LightClientState = LightValidationState<B>>,
{
check_validator_set_proof::<B>(
params.genesis_header.state_root(),
Expand Down Expand Up @@ -210,7 +214,7 @@ where
B: Block,
NumberFor<B>: finality_grandpa::BlockNumberOps,
OCallApi: EnclaveOnChainOCallApi,
LightClientSeal: LightClientSealing<LightValidationState<B>>,
LightClientSeal: LightClientSealing<LightClientState = LightValidationState<B>>,
{
if !seal.exists() {
info!("[Enclave] ChainRelay DB not found, creating new! {}", seal.path().display());
Expand Down
8 changes: 5 additions & 3 deletions core/parentchain/light-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,11 @@ pub trait LightClientState<Block: ParentchainBlockTrait> {
fn penultimate_finalized_block_header(&self) -> Result<Block::Header, Error>;
}

pub trait LightClientSealing<LightClientState> {
fn seal(&self, state: &LightClientState) -> Result<(), Error>;
fn unseal(&self) -> Result<LightClientState, Error>;
pub trait LightClientSealing {
type LightClientState;

fn seal(&self, state: &Self::LightClientState) -> Result<(), Error>;
fn unseal(&self) -> Result<Self::LightClientState, Error>;
fn exists(&self) -> bool;
fn path(&self) -> &Path;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ impl Default for LightValidationStateSealMock {
}
}

impl LightClientSealing<LightValidationState<Block>> for LightValidationStateSealMock {
impl LightClientSealing for LightValidationStateSealMock {
type LightClientState = LightValidationState<Block>;

fn unseal(&self) -> Result<LightValidationState<Block>, Error> {
Ok(LightValidationState::new(RelayState::new(
ParentchainHeaderBuilder::default().build(),
Expand Down
8 changes: 6 additions & 2 deletions enclave-runtime/src/initialization/global_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,12 @@ pub type EnclaveSidechainBlockImportQueueWorker = BlockImportQueueWorker<
EnclaveSidechainBlockImportQueue,
EnclaveSidechainBlockSyncer,
>;
pub type EnclaveSealHandler =
SealHandler<EnclaveShieldingKeyRepository, EnclaveStateKeyRepository, EnclaveStateHandler>;
pub type EnclaveSealHandler = SealHandler<
EnclaveShieldingKeyRepository,
EnclaveStateKeyRepository,
EnclaveStateHandler,
EnclaveLightClientSeal,
>;
pub type EnclaveOffchainWorkerExecutor = itc_offchain_worker_executor::executor::Executor<
ParentchainBlock,
EnclaveTopPoolAuthor,
Expand Down
13 changes: 12 additions & 1 deletion enclave-runtime/src/tls_ra/mocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,17 @@ pub struct SealHandlerMock {
pub shielding_key: Arc<RwLock<Vec<u8>>>,
pub state_key: Arc<RwLock<Vec<u8>>>,
pub state: Arc<RwLock<Vec<u8>>>,
pub light_client_state: Arc<RwLock<Vec<u8>>>,
}

impl SealHandlerMock {
pub fn new(
shielding_key: Arc<RwLock<Vec<u8>>>,
state_key: Arc<RwLock<Vec<u8>>>,
state: Arc<RwLock<Vec<u8>>>,
light_client_state: Arc<RwLock<Vec<u8>>>,
) -> Self {
Self { shielding_key, state_key, state }
Self { shielding_key, state_key, state, light_client_state }
}
}

Expand All @@ -59,6 +61,11 @@ impl SealStateAndKeys for SealHandlerMock {
fn seal_new_empty_state(&self, _shard: &ShardIdentifier) -> EnclaveResult<()> {
Ok(())
}

fn seal_light_client_state(&self, bytes: &[u8]) -> EnclaveResult<()> {
*self.light_client_state.write().unwrap() = bytes.to_vec();
Ok(())
}
}

impl UnsealStateAndKeys for SealHandlerMock {
Expand All @@ -73,4 +80,8 @@ impl UnsealStateAndKeys for SealHandlerMock {
fn unseal_state(&self, _shard: &ShardIdentifier) -> EnclaveResult<Vec<u8>> {
Ok(self.state.read().unwrap().clone())
}

fn unseal_light_client_state(&self) -> EnclaveResult<Vec<u8>> {
Ok(self.light_client_state.read().unwrap().clone())
}
}
56 changes: 34 additions & 22 deletions enclave-runtime/src/tls_ra/seal_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,33 +35,23 @@ use std::{sync::Arc, vec::Vec};

/// Handles the sealing and unsealing of the shielding key, state key and the state.
#[derive(Default)]
pub struct SealHandler<ShieldingKeyRepository, StateKeyRepository, StateHandler>
where
ShieldingKeyRepository: AccessKey<KeyType = Rsa3072KeyPair> + MutateKey<Rsa3072KeyPair>,
StateKeyRepository: AccessKey<KeyType = Aes> + MutateKey<Aes>,
// Constraint StateT = StfState currently necessary because SgxExternalities Encode/Decode does not work.
// See https://github.com/integritee-network/sgx-runtime/issues/46.
StateHandler: HandleState<StateT = StfState>,
{
pub struct SealHandler<ShieldingKeyRepository, StateKeyRepository, StateHandler, LightClientSeal> {
state_handler: Arc<StateHandler>,
state_key_repository: Arc<StateKeyRepository>,
shielding_key_repository: Arc<ShieldingKeyRepository>,
light_client_seal: LightClientSealing,
light_client_seal: Arc<LightClientSeal>,
}

impl<ShieldingKeyRepository, StateKeyRepository, StateHandler>
SealHandler<ShieldingKeyRepository, StateKeyRepository, StateHandler>
where
ShieldingKeyRepository: AccessKey<KeyType = Rsa3072KeyPair> + MutateKey<Rsa3072KeyPair>,
StateKeyRepository: AccessKey<KeyType = Aes> + MutateKey<Aes>,
StateHandler: HandleState<StateT = StfState>,
impl<ShieldingKeyRepository, StateKeyRepository, StateHandler, LightClientSeal>
SealHandler<ShieldingKeyRepository, StateKeyRepository, StateHandler, LightClientSeal>
{
pub fn new(
state_handler: Arc<StateHandler>,
state_key_repository: Arc<StateKeyRepository>,
shielding_key_repository: Arc<ShieldingKeyRepository>,
light_client_seal: Arc<LightClientSeal>,
) -> Self {
Self { state_handler, state_key_repository, shielding_key_repository }
Self { state_handler, state_key_repository, shielding_key_repository, light_client_seal }
}
}

Expand All @@ -70,20 +60,24 @@ pub trait SealStateAndKeys {
fn seal_state_key(&self, bytes: &[u8]) -> EnclaveResult<()>;
fn seal_state(&self, bytes: &[u8], shard: &ShardIdentifier) -> EnclaveResult<()>;
fn seal_new_empty_state(&self, shard: &ShardIdentifier) -> EnclaveResult<()>;
fn seal_light_client_state(&self, bytes: &[u8]) -> EnclaveResult<()>;
}

pub trait UnsealStateAndKeys {
fn unseal_shielding_key(&self) -> EnclaveResult<Vec<u8>>;
fn unseal_state_key(&self) -> EnclaveResult<Vec<u8>>;
fn unseal_state(&self, shard: &ShardIdentifier) -> EnclaveResult<Vec<u8>>;
fn unseal_light_client_state(&self) -> EnclaveResult<Vec<u8>>;
}

impl<ShieldingKeyRepository, StateKeyRepository, StateHandler> SealStateAndKeys
for SealHandler<ShieldingKeyRepository, StateKeyRepository, StateHandler>
impl<ShieldingKeyRepository, StateKeyRepository, StateHandler, LightClientSeal> SealStateAndKeys
for SealHandler<ShieldingKeyRepository, StateKeyRepository, StateHandler, LightClientSeal>
where
ShieldingKeyRepository: AccessKey<KeyType = Rsa3072KeyPair> + MutateKey<Rsa3072KeyPair>,
StateKeyRepository: AccessKey<KeyType = Aes> + MutateKey<Aes>,
StateHandler: HandleState<StateT = StfState>,
LightClientSeal: LightClientSealing,
LightClientSeal::LightClientState: Decode,
{
fn seal_shielding_key(&self, bytes: &[u8]) -> EnclaveResult<()> {
let key: Rsa3072KeyPair = serde_json::from_slice(bytes).map_err(|e| {
Expand Down Expand Up @@ -111,6 +105,13 @@ where
Ok(())
}

fn seal_light_client_state(&self, mut bytes: &[u8]) -> EnclaveResult<()> {
let state = <LightClientSeal as LightClientSealing>::LightClientState::decode(&mut bytes)?;
self.light_client_seal.seal(&state)?;
info!("Successfully sealed light client state");
Ok(())
}

/// Seal an empty, newly initialized state.
///
/// Requires the shielding key to be sealed and updated before calling this.
Expand All @@ -125,12 +126,14 @@ where
}
}

impl<ShieldingKeyRepository, StateKeyRepository, StateHandler> UnsealStateAndKeys
for SealHandler<ShieldingKeyRepository, StateKeyRepository, StateHandler>
impl<ShieldingKeyRepository, StateKeyRepository, StateHandler, LightClientSeal> UnsealStateAndKeys
for SealHandler<ShieldingKeyRepository, StateKeyRepository, StateHandler, LightClientSeal>
where
ShieldingKeyRepository: AccessKey<KeyType = Rsa3072KeyPair> + MutateKey<Rsa3072KeyPair>,
StateKeyRepository: AccessKey<KeyType = Aes> + MutateKey<Aes>,
StateHandler: HandleState<StateT = StfState>,
LightClientSeal: LightClientSealing,
LightClientSeal::LightClientState: Encode,
{
fn unseal_shielding_key(&self) -> EnclaveResult<Vec<u8>> {
let shielding_key = self
Expand All @@ -150,19 +153,28 @@ where
fn unseal_state(&self, shard: &ShardIdentifier) -> EnclaveResult<Vec<u8>> {
Ok(self.state_handler.execute_on_current(shard, |state, _| state.state.encode())?)
}

fn unseal_light_client_state(&self) -> EnclaveResult<Vec<u8>> {
Ok(self.light_client_seal.unseal()?.encode())
}
}

#[cfg(feature = "test")]
pub mod test {
use super::*;
use itc_parentchain::light_client::mocks::validator_mock_seal::LightValidationStateSealMock;
use itp_sgx_crypto::mocks::KeyRepositoryMock;
use itp_test::mock::handle_state_mock::HandleStateMock;

type StateKeyRepositoryMock = KeyRepositoryMock<Aes>;
type ShieldingKeyRepositoryMock = KeyRepositoryMock<Rsa3072KeyPair>;

type SealHandlerMock =
SealHandler<ShieldingKeyRepositoryMock, StateKeyRepositoryMock, HandleStateMock>;
type SealHandlerMock = SealHandler<
ShieldingKeyRepositoryMock,
StateKeyRepositoryMock,
HandleStateMock,
LightValidationStateSealMock,
>;

pub fn seal_shielding_key_works() {
let seal_handler = SealHandlerMock::default();
Expand Down
12 changes: 11 additions & 1 deletion enclave-runtime/src/tls_ra/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::{
tls_ra::seal_handler::{SealHandler, SealStateAndKeys, UnsealStateAndKeys},
};
use ita_stf::State;
use itc_parentchain::light_client::mocks::validator_mock_seal::LightValidationStateSealMock;
use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider};
use itp_sgx_crypto::{mocks::KeyRepositoryMock, Aes};
use itp_stf_interface::InitState;
Expand Down Expand Up @@ -74,22 +75,28 @@ pub fn test_tls_ra_server_client_networking() {
let shielding_key_encoded = vec![1, 2, 3];
let state_key_encoded = vec![5, 2, 3, 7];
let state_encoded = Vec::from([1u8; 26000]); // Have a decently sized state, so read() must be called multiple times.
let light_client_state_encoded = Vec::from([1u8; 10000]); // Have a decently sized state, so read() must be called multiple times.

let server_seal_handler = SealHandlerMock::new(
Arc::new(RwLock::new(shielding_key_encoded.clone())),
Arc::new(RwLock::new(state_key_encoded.clone())),
Arc::new(RwLock::new(state_encoded.clone())),
Arc::new(RwLock::new(light_client_state_encoded.clone())),
);
let initial_client_state = vec![0, 0, 1];
let initial_client_state_key = vec![0, 0, 2];
let initial_client_light_client_state = vec![0, 0, 3];
let client_shielding_key = Arc::new(RwLock::new(Vec::new()));
let client_state_key = Arc::new(RwLock::new(initial_client_state_key.clone()));
let client_state = Arc::new(RwLock::new(initial_client_state.clone()));
let client_light_client_state =
Arc::new(RwLock::new(initial_client_light_client_state.clone()));

let client_seal_handler = SealHandlerMock::new(
client_shielding_key.clone(),
client_state_key.clone(),
client_state.clone(),
client_light_client_state.clone(),
);

let port: u16 = 3149;
Expand Down Expand Up @@ -118,6 +125,7 @@ pub fn test_tls_ra_server_client_networking() {

assert!(result.is_ok());
assert_eq!(*client_shielding_key.read().unwrap(), shielding_key_encoded);
assert_eq!(*client_light_client_state.read().unwrap(), light_client_state_encoded);

// State and state-key are provisioned only in sidechain mode
if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain {
Expand Down Expand Up @@ -179,5 +187,7 @@ fn create_seal_handler(
Arc::new(KeyRepositoryMock::<Rsa3072KeyPair>::new(shielding_key));
let state_handler = Arc::new(HandleStateMock::default());
state_handler.reset(state, shard).unwrap();
SealHandler::new(state_handler, state_key_repository, shielding_key_repository)
let seal = Arc::new(LightValidationStateSealMock::new());

SealHandler::new(state_handler, state_key_repository, shielding_key_repository, seal)
}
19 changes: 16 additions & 3 deletions enclave-runtime/src/tls_ra/tls_ra_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
attestation::create_ra_report_and_signature,
error::{Error as EnclaveError, Result as EnclaveResult},
initialization::global_components::{
EnclaveSealHandler, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT,
EnclaveSealHandler, GLOBAL_LIGHT_CLIENT_SEAL, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT,
GLOBAL_STATE_KEY_REPOSITORY_COMPONENT,
},
ocall::OcallApi,
Expand Down Expand Up @@ -128,6 +128,7 @@ where
Opcode::ShieldingKey => self.seal_handler.seal_shielding_key(&bytes)?,
Opcode::StateKey => self.seal_handler.seal_state_key(&bytes)?,
Opcode::State => self.seal_handler.seal_state(&bytes, &self.shard)?,
Opcode::LightClient => self.seal_handler.seal_light_client_state(&bytes)?,
};
Ok(Some(header.opcode))
}
Expand Down Expand Up @@ -192,8 +193,20 @@ pub unsafe extern "C" fn request_state_provisioning(
},
};

let seal_handler =
EnclaveSealHandler::new(state_handler, state_key_repository, shielding_key_repository);
let light_client_seal = match GLOBAL_LIGHT_CLIENT_SEAL.get() {
Ok(s) => s,
Err(e) => {
error!("{:?}", e);
return sgx_status_t::SGX_ERROR_UNEXPECTED
},
};

let seal_handler = EnclaveSealHandler::new(
state_handler,
state_key_repository,
shielding_key_repository,
light_client_seal,
);

if let Err(e) = request_state_provisioning_internal(
socket_fd,
Expand Down
Loading

0 comments on commit 33db450

Please sign in to comment.