Skip to content
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

Allow setting a base path for shielding-key file IO #1318

Merged
merged 16 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from 13 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
25 changes: 24 additions & 1 deletion core-primitives/sgx/crypto/src/key_repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ use std::sync::SgxRwLock as RwLock;
#[cfg(feature = "std")]
use std::sync::RwLock;

use crate::error::{Error, Result};
use crate::{
error::{Error, Result},
ToPubkey,
};
use itp_sgx_io::SealedIO;
use std::sync::Arc;

Expand All @@ -32,6 +35,13 @@ pub trait AccessKey {
fn retrieve_key(&self) -> Result<Self::KeyType>;
}

/// Access a cryptographic public key.
pub trait AccessPubkey {
type KeyType;

fn retrieve_pubkey(&self) -> Result<Self::KeyType>;
}

/// Mutate a cryptographic key.
pub trait MutateKey<KeyType> {
fn update_key(&self, key: KeyType) -> Result<()>;
Expand Down Expand Up @@ -62,6 +72,19 @@ where
}
}

impl<Pair, SealedIo> AccessPubkey for KeyRepository<Pair, SealedIo>
where
Pair: ToPubkey<Error = crate::error::Error> + Clone,
SealedIo: SealedIO<Unsealed = Pair, Error = crate::error::Error>,
{
type KeyType = <Pair as ToPubkey>::Pubkey;

fn retrieve_pubkey(&self) -> Result<Self::KeyType> {
let pair = self.key_lock.read().map_err(|_| Error::LockPoisoning).map(|l| l.clone())?;
clangenb marked this conversation as resolved.
Show resolved Hide resolved
pair.pubkey()
}
}

impl<KeyType, SealedIo> MutateKey<KeyType> for KeyRepository<KeyType, SealedIo>
where
KeyType: Clone,
Expand Down
110 changes: 74 additions & 36 deletions core-primitives/sgx/crypto/src/rsa3072.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::sgx_reexport_prelude::*;
use crate::{
error::{Error, Result},
traits::{ShieldingCryptoDecrypt, ShieldingCryptoEncrypt},
ToPubkey,
};
use sgx_crypto_helper::{
rsa3072::{Rsa3072KeyPair, Rsa3072PubKey},
Expand Down Expand Up @@ -64,56 +65,88 @@ impl ShieldingCryptoEncrypt for Rsa3072PubKey {
}
}

impl ToPubkey for Rsa3072KeyPair {
type Error = Error;
type Pubkey = Rsa3072PubKey;

fn pubkey(&self) -> Result<Self::Pubkey> {
self.export_pubkey().map_err(|e| Error::Other(format!("{:?}", e).into()))
coax1d marked this conversation as resolved.
Show resolved Hide resolved
}
}

pub trait RsaSealing {
fn unseal_pubkey(&self) -> Result<Rsa3072PubKey>;

fn unseal_pair(&self) -> Result<Rsa3072KeyPair>;

fn exists(&self) -> bool;

fn create_sealed_if_absent(&self) -> Result<()>;

fn create_sealed(&self) -> Result<()>;
}

#[cfg(feature = "sgx")]
pub mod sgx {
use super::*;
use derive_more::Display;
use crate::key_repository::KeyRepository;
use itp_settings::files::RSA3072_SEALED_KEY_FILE;
use itp_sgx_io::{seal, unseal, SealedIO, StaticSealedIO};
use itp_sgx_io::{seal, unseal, SealedIO};
use log::*;
use std::sgxfs::SgxFile;
use std::{path::PathBuf, sgxfs::SgxFile};

/// Gets a repository for an Rsa3072 keypair and initializes
/// a fresh key pair if it doesn't exist at `path`.
pub fn get_rsa3072_repository(
path: PathBuf,
) -> Result<KeyRepository<Rsa3072KeyPair, Rsa3072Seal>> {
let rsa_seal = Rsa3072Seal::new(path);
rsa_seal.create_sealed_if_absent()?;
let shielding_key = rsa_seal.unseal_pair()?;
Ok(KeyRepository::new(shielding_key, rsa_seal.into()))
}

#[derive(Clone, Debug)]
pub struct Rsa3072Seal {
base_path: PathBuf,
}

impl Rsa3072Seal {
pub fn unseal_pubkey() -> Result<Rsa3072PubKey> {
let pair = Self::unseal_from_static_file()?;
let pubkey =
pair.export_pubkey().map_err(|e| Error::Other(format!("{:?}", e).into()))?;
Ok(pubkey)
pub fn new(base_path: PathBuf) -> Self {
Self { base_path }
}
}

pub fn create_sealed_if_absent() -> Result<()> {
if SgxFile::open(RSA3072_SEALED_KEY_FILE).is_err() {
info!("[Enclave] Keyfile not found, creating new! {}", RSA3072_SEALED_KEY_FILE);
return create_sealed()
pub fn path(&self) -> PathBuf {
self.base_path.join(RSA3072_SEALED_KEY_FILE)
}
Ok(())
}

pub fn create_sealed() -> Result<()> {
let rsa_keypair =
Rsa3072KeyPair::new().map_err(|e| Error::Other(format!("{:?}", e).into()))?;
// println!("[Enclave] generated RSA3072 key pair. Cleartext: {}", rsa_key_json);
Rsa3072Seal::seal_to_static_file(&rsa_keypair)
}
impl RsaSealing for Rsa3072Seal {
fn unseal_pubkey(&self) -> Result<Rsa3072PubKey> {
self.unseal()?.pubkey()
}

#[derive(Copy, Clone, Debug, Display)]
pub struct Rsa3072Seal;
fn unseal_pair(&self) -> Result<Rsa3072KeyPair> {
self.unseal()
}

impl StaticSealedIO for Rsa3072Seal {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the static implementation.

type Error = Error;
type Unsealed = Rsa3072KeyPair;
fn unseal_from_static_file() -> Result<Self::Unsealed> {
let raw = unseal(RSA3072_SEALED_KEY_FILE)?;
let key: Rsa3072KeyPair = serde_json::from_slice(&raw)
.map_err(|e| Error::Other(format!("{:?}", e).into()))?;
Ok(key.into())
fn exists(&self) -> bool {
clangenb marked this conversation as resolved.
Show resolved Hide resolved
SgxFile::open(self.path()).is_ok()
}

fn seal_to_static_file(unsealed: &Self::Unsealed) -> Result<()> {
let key_json = serde_json::to_vec(&unsealed)
.map_err(|e| Error::Other(format!("{:?}", e).into()))?;
Ok(seal(&key_json, RSA3072_SEALED_KEY_FILE)?)
fn create_sealed_if_absent(&self) -> Result<()> {
if !self.exists() {
info!("Keyfile not found, creating new! {}", self.path().display());
return self.create_sealed()
}
Ok(())
}

fn create_sealed(&self) -> Result<()> {
let rsa_keypair =
Rsa3072KeyPair::new().map_err(|e| Error::Other(format!("{:?}", e).into()))?;
info!("Generated RSA3072 key pair. PubKey: {:?}", rsa_keypair.pubkey()?);
self.seal(&rsa_keypair)
}
}

Expand All @@ -122,11 +155,16 @@ pub mod sgx {
type Unsealed = Rsa3072KeyPair;

fn unseal(&self) -> Result<Self::Unsealed> {
Self::unseal_from_static_file()
let raw = unseal(self.path())?;
let key: Rsa3072KeyPair = serde_json::from_slice(&raw)
.map_err(|e| Error::Other(format!("{:?}", e).into()))?;
Ok(key.into())
}

fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> {
Self::seal_to_static_file(unsealed)
let key_json = serde_json::to_vec(&unsealed)
.map_err(|e| Error::Other(format!("{:?}", e).into()))?;
Ok(seal(&key_json, self.path())?)
}
}
}
7 changes: 7 additions & 0 deletions core-primitives/sgx/crypto/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,10 @@ pub trait ShieldingCryptoDecrypt {
type Error: Debug;
fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>, Self::Error>;
}

pub trait ToPubkey {
type Error: Debug;
type Pubkey;

fn pubkey(&self) -> Result<Self::Pubkey, Self::Error>;
}
2 changes: 2 additions & 0 deletions enclave-runtime/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ dependencies = [
"itp-sgx-crypto",
"itp-sgx-externalities",
"itp-sgx-io",
"itp-sgx-temp-dir",
"itp-stf-executor",
"itp-stf-interface",
"itp-stf-primitives",
Expand All @@ -721,6 +722,7 @@ dependencies = [
"lazy_static",
"log",
"multibase",
"once_cell 1.4.0",
"parity-scale-codec",
"primitive-types",
"rust-base58",
Expand Down
6 changes: 6 additions & 0 deletions enclave-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ test = [
"itp-attestation-handler/test",
"itp-extrinsics-factory/mocks",
"itp-sgx-crypto/mocks",
"itp-sgx-temp-dir",
"itp-stf-executor/test",
"itp-stf-executor/mocks",
"itp-stf-state-handler/test",
Expand Down Expand Up @@ -74,6 +75,8 @@ jsonrpc-core = { default-features = false, git = "https://github.com/scs/jsonrpc
# mesalock
env_logger = { git = "https://github.com/integritee-network/env_logger-sgx" }
log = { git = "https://github.com/integritee-network/log-sgx" }
# Todo #1313: use the `once_cell` included in rusts core library once we use rust v1.70.0
once_cell = { git = "https://github.com/mesalock-linux/once_cell-sgx" }
rustls = { rev = "sgx_1.1.3", features = ["dangerous_configuration"], git = "https://github.com/mesalock-linux/rustls" }
serde = { tag = "sgx_1.1.3", git = "https://github.com/mesalock-linux/serde-sgx", features = ["alloc", "mesalock_sgx"] }
serde_derive = { git = "https://github.com/mesalock-linux/serde-sgx" }
Expand Down Expand Up @@ -134,6 +137,9 @@ sp-core = { default-features = false, features = ["full_crypto"], git = "https:/
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.39" }
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.39" }

# test-deps
itp-sgx-temp-dir = { version = "0.1", default-features = false, optional = true, path = "../core-primitives/sgx/temp-dir" }

[patch.crates-io]
env_logger = { git = "https://github.com/integritee-network/env_logger-sgx" }
getrandom = { git = "https://github.com/integritee-network/getrandom-sgx", branch = "update-v2.3" }
Expand Down
25 changes: 11 additions & 14 deletions enclave-runtime/src/initialization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use itp_attestation_handler::IntelAttestationHandler;
use itp_component_container::{ComponentGetter, ComponentInitializer};
use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE;
use itp_settings::files::STATE_SNAPSHOTS_CACHE_SIZE;
use itp_sgx_crypto::{aes, ed25519, rsa3072, AesSeal, Ed25519Seal, Rsa3072Seal};
use itp_sgx_crypto::{aes, ed25519, get_rsa3072_repository, AesSeal, Ed25519Seal};
use itp_sgx_io::StaticSealedIO;
use itp_stf_state_handler::{
handle_state::HandleState, query_shard_state::QueryShardState,
Expand All @@ -73,22 +73,18 @@ use itp_types::ShardIdentifier;
use its_sidechain::block_composer::BlockComposer;
use log::*;
use sp_core::crypto::Pair;
use std::{collections::HashMap, string::String, sync::Arc};

pub(crate) fn init_enclave(mu_ra_url: String, untrusted_worker_url: String) -> EnclaveResult<()> {
// Initialize the logging environment in the enclave.
env_logger::init();
use std::{collections::HashMap, path::PathBuf, string::String, sync::Arc};

pub(crate) fn init_enclave(
mu_ra_url: String,
untrusted_worker_url: String,
base_dir: PathBuf,
) -> EnclaveResult<()> {
ed25519::create_sealed_if_absent().map_err(Error::Crypto)?;
let signer = Ed25519Seal::unseal_from_static_file().map_err(Error::Crypto)?;
info!("[Enclave initialized] Ed25519 prim raw : {:?}", signer.public().0);

rsa3072::create_sealed_if_absent()?;

let shielding_key = Rsa3072Seal::unseal_from_static_file()?;

let shielding_key_repository =
Arc::new(EnclaveShieldingKeyRepository::new(shielding_key, Arc::new(Rsa3072Seal)));
let shielding_key_repository = Arc::new(get_rsa3072_repository(base_dir.clone())?);
GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.initialize(shielding_key_repository.clone());

// Create the aes key that is used for state encryption such that a key is always present in tests.
Expand Down Expand Up @@ -153,12 +149,13 @@ pub(crate) fn init_enclave(mu_ra_url: String, untrusted_worker_url: String) -> E
connection_registry.clone(),
state_handler,
ocall_api.clone(),
shielding_key_repository,
shielding_key_repository.clone(),
);
GLOBAL_TOP_POOL_AUTHOR_COMPONENT.initialize(top_pool_author.clone());

let getter_executor = Arc::new(EnclaveGetterExecutor::new(state_observer));
let io_handler = public_api_rpc_handler(top_pool_author, getter_executor);
let io_handler =
public_api_rpc_handler(top_pool_author, getter_executor, shielding_key_repository);
let rpc_handler = Arc::new(RpcWsHandler::new(io_handler, watch_extractor, connection_registry));
GLOBAL_RPC_WS_HANDLER_COMPONENT.initialize(rpc_handler);

Expand Down
34 changes: 29 additions & 5 deletions enclave-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ use crate::{
error::{Error, Result},
initialization::global_components::{
GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT, GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT,
GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT,
GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT,
GLOBAL_STATE_HANDLER_COMPONENT,
},
rpc::worker_api_direct::sidechain_io_handler,
utils::{
Expand All @@ -50,16 +51,17 @@ use itp_import_queue::PushToQueue;
use itp_node_api::metadata::NodeMetadata;
use itp_nonce_cache::{MutateNonce, Nonce, GLOBAL_NONCE_CACHE};
use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider};
use itp_sgx_crypto::{ed25519, Ed25519Seal, Rsa3072Seal};
use itp_sgx_crypto::{ed25519, key_repository::AccessPubkey, Ed25519Seal};
use itp_sgx_io::StaticSealedIO;
use itp_storage::{StorageProof, StorageProofChecker};
use itp_types::{ShardIdentifier, SignedBlock};
use itp_utils::write_slice_and_whitespace_pad;
use log::*;
use once_cell::sync::OnceCell;
use sgx_types::sgx_status_t;
use sp_core::crypto::Pair;
use sp_runtime::traits::BlakeTwo256;
use std::{boxed::Box, slice, vec::Vec};
use std::{boxed::Box, path::PathBuf, slice, vec::Vec};

mod attestation;
mod empty_impls;
Expand All @@ -83,6 +85,8 @@ pub mod test;
pub type Hash = sp_core::H256;
pub type AuthorityPair = sp_core::ed25519::Pair;

static BASE_PATH: OnceCell<PathBuf> = OnceCell::new();

/// Initialize the enclave.
#[no_mangle]
pub unsafe extern "C" fn init(
Expand All @@ -91,6 +95,18 @@ pub unsafe extern "C" fn init(
untrusted_worker_addr: *const u8,
untrusted_worker_addr_size: u32,
) -> sgx_status_t {
// Initialize the logging environment in the enclave.
env_logger::init();
Comment on lines +98 to +99
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this form initialization::init_enclave to be able to log here.


// Todo: This will be changed to be a param of the `init` ecall:
// https://github.com/integritee-network/worker/issues/1292
//
// Until the above task is finished, we just fall back to the
// static behaviour, which uses the PWD already.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// static behaviour, which uses the PWD already.
// static behavior, which uses the PWD already.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, do you hate the British? ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought code was universal American English 👯‍♂️

let pwd = std::env::current_dir().expect("Works on all supported platforms; qed");
info!("Setting base_dir to pwd: {}", pwd.display());
BASE_PATH.set(pwd.clone()).expect("We only init this once here; qed.");

let mu_ra_url =
match String::decode(&mut slice::from_raw_parts(mu_ra_addr, mu_ra_addr_size as usize))
.map_err(Error::Codec)
Expand All @@ -109,7 +125,7 @@ pub unsafe extern "C" fn init(
Err(e) => return e.into(),
};

match initialization::init_enclave(mu_ra_url, untrusted_worker_url) {
match initialization::init_enclave(mu_ra_url, untrusted_worker_url, pwd) {
Err(e) => e.into(),
Ok(()) => sgx_status_t::SGX_SUCCESS,
}
Expand All @@ -120,7 +136,15 @@ pub unsafe extern "C" fn get_rsa_encryption_pubkey(
pubkey: *mut u8,
pubkey_size: u32,
) -> sgx_status_t {
let rsa_pubkey = match Rsa3072Seal::unseal_pubkey() {
let shielding_key_repository = match GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get() {
Ok(s) => s,
Err(e) => {
error!("{:?}", e);
return sgx_status_t::SGX_ERROR_UNEXPECTED
},
};

let rsa_pubkey = match shielding_key_repository.retrieve_pubkey() {
Ok(key) => key,
Err(e) => return e.into(),
};
Expand Down
Loading