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 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
1 change: 0 additions & 1 deletion core-primitives/settings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ pub mod files {
pub static SIDECHAIN_PURGE_LIMIT: u64 = 100; // keep the last.. sidechainblocks when purging

// used by enclave
pub const RSA3072_SEALED_KEY_FILE: &str = "rsa3072_key_sealed.bin";
pub const SEALED_SIGNER_SEED_FILE: &str = "ed25519_key_sealed.bin";
pub const AES_KEY_FILE_AND_INIT_V: &str = "aes_key_sealed.bin";
pub const LIGHT_CLIENT_DB: &str = "light_client_db.bin";
Expand Down
24 changes: 23 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,18 @@ 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> {
self.key_lock.read().map_err(|_| Error::LockPoisoning).map(|p| p.pubkey())?
}
}

impl<KeyType, SealedIo> MutateKey<KeyType> for KeyRepository<KeyType, SealedIo>
where
KeyType: Clone,
Expand Down
114 changes: 77 additions & 37 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 All @@ -31,6 +32,9 @@ use std::vec::Vec;
#[cfg(feature = "sgx")]
pub use sgx::*;

/// File name of the sealed RSA key file.
pub const RSA3072_SEALED_KEY_FILE: &str = "rsa3072_key_sealed.bin";

impl ShieldingCryptoEncrypt for Rsa3072KeyPair {
type Error = Error;

Expand Down Expand Up @@ -64,56 +68,87 @@ 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()))
}
}

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 itp_settings::files::RSA3072_SEALED_KEY_FILE;
use itp_sgx_io::{seal, unseal, SealedIO, StaticSealedIO};
use crate::key_repository::KeyRepository;
use itp_sgx_io::{seal, unseal, SealedIO};
use log::*;
use std::sgxfs::SgxFile;
use std::path::PathBuf;

/// 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 {
self.path().exists()
}

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 +157,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)?);
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
Loading