Skip to content

Commit

Permalink
Allow setting a base path for shielding-key file IO (#1318)
Browse files Browse the repository at this point in the history
* [itp-sgx-crypto] add `ToPubkey` and `AccessPubkey` traits

* [itp-sgx-crypto] refactor the Rsa3072 stuff to no longer use static file IO.

* [itp-sgx-crypto] set-base-path to the PWD

* [enclave-runtime] more explanation about using the PWD

* [enclave-runtime] add todo for replacing the once-cell.

* taplo fmt

* add some doc

* typo

* [sgx-crypto] log full path instead of just filename.

* [enclave-runtime] add todo for replacing `once_cell`

* [itp-sgx-crypto] log the pubKey of the RSA key when it is generated.

* fix clippy

* [itp-sgx-crypto] move the file name of the rsa-key from itp-settings to the rsa file.

* [itp-sgx-crypto] remove unnecessary clone.
  • Loading branch information
clangenb authored May 24, 2023
1 parent 6206b36 commit 14c65e2
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 65 deletions.
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 {
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

0 comments on commit 14c65e2

Please sign in to comment.