Skip to content

Commit

Permalink
Dump private keys in non-prod (#2501)
Browse files Browse the repository at this point in the history
* init

* fix compile

* add command

* refinement

* fix clippy

* remove comma
  • Loading branch information
Kailai-Wang committed Feb 19, 2024
1 parent 08454ad commit 09c9022
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 2 deletions.
2 changes: 2 additions & 0 deletions bitacross-worker/Cargo.lock

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

1 change: 1 addition & 0 deletions bitacross-worker/core-primitives/enclave-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "po
itc-parentchain = { path = "../../core/parentchain/parentchain-crate" }
itp-enclave-api-ffi = { path = "ffi" }
itp-settings = { path = "../settings" }
itp-sgx-crypto = { path = "../sgx/crypto" }
itp-storage = { path = "../storage" }
itp-types = { path = "../types" }

Expand Down
14 changes: 14 additions & 0 deletions bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,20 @@ extern "C" {
pubkey_size: u32,
) -> sgx_status_t;

pub fn get_bitcoin_wallet_pair(
eid: sgx_enclave_id_t,
retval: *mut sgx_status_t,
pair: *mut u8,
pair_size: u32,
) -> sgx_status_t;

pub fn get_ethereum_wallet_pair(
eid: sgx_enclave_id_t,
retval: *mut sgx_status_t,
pair: *mut u8,
pair_size: u32,
) -> sgx_status_t;

pub fn get_mrenclave(
eid: sgx_enclave_id_t,
retval: *mut sgx_status_t,
Expand Down
49 changes: 48 additions & 1 deletion bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::EnclaveResult;
use codec::Decode;
use core::fmt::Debug;
use itc_parentchain::primitives::{ParentchainId, ParentchainInitParams};
use itp_sgx_crypto::{ecdsa, schnorr};
use itp_types::ShardIdentifier;
use pallet_teebag::EnclaveFingerprint;
use sgx_crypto_helper::rsa3072::Rsa3072PubKey;
Expand Down Expand Up @@ -72,6 +73,12 @@ pub trait EnclaveBase: Send + Sync + 'static {
/// retrieve vault account from shard state
fn get_ecc_vault_pubkey(&self, shard: &ShardIdentifier) -> EnclaveResult<ed25519::Public>;

/// retrieve the btc wallet key pair, only works in non-prod
fn get_bitcoin_wallet_pair(&self) -> EnclaveResult<schnorr::Pair>;

/// retrieve the eth wallet key pair, only works in non-prod
fn get_ethereum_wallet_pair(&self) -> EnclaveResult<ecdsa::Pair>;

fn get_fingerprint(&self) -> EnclaveResult<EnclaveFingerprint>;

// litentry
Expand All @@ -84,7 +91,7 @@ pub trait EnclaveBase: Send + Sync + 'static {
/// EnclaveApi implementation for Enclave struct
#[cfg(feature = "implement-ffi")]
mod impl_ffi {
use super::EnclaveBase;
use super::{ecdsa, schnorr, EnclaveBase};
use crate::{error::Error, Enclave, EnclaveResult};
use codec::{Decode, Encode};
use core::fmt::Debug;
Expand Down Expand Up @@ -326,6 +333,46 @@ mod impl_ffi {
Ok(ed25519::Public::from_raw(pubkey))
}

fn get_bitcoin_wallet_pair(&self) -> EnclaveResult<schnorr::Pair> {
let mut retval = sgx_status_t::SGX_SUCCESS;
let mut private_key = [0u8; 32];

let result = unsafe {
ffi::get_bitcoin_wallet_pair(
self.eid,
&mut retval,
private_key.as_mut_ptr(),
private_key.len() as u32,
)
};

ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result));
ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval));

schnorr::Pair::from_bytes(&private_key)
.map_err(|e| Error::Other(format!("{:?}", e).into()))
}

fn get_ethereum_wallet_pair(&self) -> EnclaveResult<ecdsa::Pair> {
let mut retval = sgx_status_t::SGX_SUCCESS;
let mut private_key = [0u8; 32];

let result = unsafe {
ffi::get_ethereum_wallet_pair(
self.eid,
&mut retval,
private_key.as_mut_ptr(),
private_key.len() as u32,
)
};

ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result));
ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval));

ecdsa::Pair::from_bytes(&private_key)
.map_err(|e| Error::Other(format!("{:?}", e).into()))
}

fn get_fingerprint(&self) -> EnclaveResult<EnclaveFingerprint> {
let mut retval = sgx_status_t::SGX_SUCCESS;
let mut mr_enclave = [0u8; MR_ENCLAVE_SIZE];
Expand Down
10 changes: 10 additions & 0 deletions bitacross-worker/core-primitives/sgx/crypto/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,20 @@ impl Pair {
Self { private, public }
}

pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
let private_key = SigningKey::from_bytes(bytes.into())
.map_err(|e| Error::Other(format!("{:?}", e).into()))?;
Ok(Self::new(private_key))
}

pub fn public_bytes(&self) -> [u8; 33] {
self.public.as_affine().to_bytes().as_slice().try_into().unwrap()
}

pub fn private_bytes(&self) -> [u8; 32] {
self.private.to_bytes().as_slice().try_into().unwrap()
}

pub fn sign(&self, payload: &[u8]) -> Result<[u8; 64]> {
let signature: Signature =
self.private.try_sign(payload).map_err(|e| Error::Other(e.to_string().into()))?;
Expand Down
11 changes: 11 additions & 0 deletions bitacross-worker/core-primitives/sgx/crypto/src/schnorr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,22 @@ impl Pair {
Self { private, public }
}

pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
let private_key =
SigningKey::from_bytes(bytes).map_err(|e| Error::Other(format!("{:?}", e).into()))?;
Ok(Self::new(private_key))
}

pub fn public_bytes(&self) -> [u8; 33] {
// safe to unwrap here
self.public.as_affine().to_bytes().as_slice().try_into().unwrap()
}

pub fn private_bytes(&self) -> [u8; 32] {
// safe to unwrap here
self.private.to_bytes().as_slice().try_into().unwrap()
}

pub fn sign(&self, payload: &[u8]) -> Result<[u8; 64]> {
let signature: Signature =
self.private.try_sign(payload).map_err(|e| Error::Other(e.to_string().into()))?;
Expand Down
6 changes: 6 additions & 0 deletions bitacross-worker/enclave-runtime/Enclave.edl
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ enclave {
public sgx_status_t get_ecc_signing_pubkey(
[out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size);

public sgx_status_t get_bitcoin_wallet_pair(
[out, size=pair_size] uint8_t* pair, uint32_t pair_size);

public sgx_status_t get_ethereum_wallet_pair(
[out, size=pair_size] uint8_t* pair, uint32_t pair_size);

public sgx_status_t get_ecc_vault_pubkey(
[in, size=shard_size] uint8_t* shard, uint32_t shard_size,
[out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size);
Expand Down
63 changes: 62 additions & 1 deletion bitacross-worker/enclave-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ use crate::{
};
use codec::Decode;
use core::ffi::c_int;
use initialization::global_components::{
GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT, GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT,
};
use itc_parentchain::{
block_import_dispatcher::DispatchBlockImport,
light_client::{concurrent_access::ValidatorAccess, Validator},
Expand All @@ -68,7 +71,7 @@ use itc_parentchain::{
use itp_component_container::ComponentGetter;
use itp_node_api::metadata::NodeMetadata;
use itp_nonce_cache::{MutateNonce, Nonce};
use itp_sgx_crypto::key_repository::AccessPubkey;
use itp_sgx_crypto::key_repository::{AccessKey, AccessPubkey};
use itp_storage::{StorageProof, StorageProofChecker};
use itp_types::{ShardIdentifier, SignedBlock};
use itp_utils::write_slice_and_whitespace_pad;
Expand Down Expand Up @@ -239,6 +242,64 @@ pub unsafe extern "C" fn get_ecc_signing_pubkey(pubkey: *mut u8, pubkey_size: u3
sgx_status_t::SGX_SUCCESS
}

#[no_mangle]
pub unsafe extern "C" fn get_bitcoin_wallet_pair(pair: *mut u8, pair_size: u32) -> sgx_status_t {
if_production_or!(
{
error!("Bitcoin wallet can only be retrieved in non-prod");
sgx_status_t::SGX_ERROR_UNEXPECTED
},
{
let bitcoin_key_repository = match GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT.get() {
Ok(s) => s,
Err(e) => {
error!("{:?}", e);
return sgx_status_t::SGX_ERROR_UNEXPECTED
},
};

let keypair = match bitcoin_key_repository.retrieve_key() {
Ok(p) => p,
Err(e) => return e.into(),
};

let privkey_slice = slice::from_raw_parts_mut(pair, pair_size as usize);
privkey_slice.clone_from_slice(&keypair.private_bytes());

sgx_status_t::SGX_SUCCESS
}
)
}

#[no_mangle]
pub unsafe extern "C" fn get_ethereum_wallet_pair(pair: *mut u8, pair_size: u32) -> sgx_status_t {
if_production_or!(
{
error!("Ethereum wallet can only be retrieved in non-prod");
sgx_status_t::SGX_ERROR_UNEXPECTED
},
{
let ethereum_key_repository = match GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT.get() {
Ok(s) => s,
Err(e) => {
error!("{:?}", e);
return sgx_status_t::SGX_ERROR_UNEXPECTED
},
};

let keypair = match ethereum_key_repository.retrieve_key() {
Ok(p) => p,
Err(e) => return e.into(),
};

let privkey_slice = slice::from_raw_parts_mut(pair, pair_size as usize);
privkey_slice.clone_from_slice(&keypair.private_bytes());

sgx_status_t::SGX_SUCCESS
}
)
}

#[no_mangle]
pub unsafe extern "C" fn set_nonce(
nonce: *const u32,
Expand Down
1 change: 1 addition & 0 deletions bitacross-worker/service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,4 @@ anyhow = "1.0.40"
mockall = "0.11"
# local
itc-parentchain-test = { path = "../core/parentchain/test" }
itp-sgx-crypto = { path = "../core-primitives/sgx/crypto" }
2 changes: 2 additions & 0 deletions bitacross-worker/service/src/cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ subcommands:
about: Get the public ed25519 key the TEE uses to sign messages and extrinsics
- dump-ra:
about: Perform RA and dump cert to disk
- wallet:
about: Print the bitcoin and ethereum custodian wallet key information, only works in non-prod
- mrenclave:
about: Dump mrenclave to stdout. base58 encoded.
- init-shard:
Expand Down
10 changes: 10 additions & 0 deletions bitacross-worker/service/src/main_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,16 @@ pub(crate) fn main() {
} else {
setup::migrate_shard(enclave.as_ref(), &old_shard, &new_shard);
}
} else if let Some(sub_matches) = matches.subcommand_matches("wallet") {
println!("Bitcoin wallet:");
let bitcoin_keypair = enclave.get_bitcoin_wallet_pair().unwrap();
println!("public : 0x{}", hex::encode(bitcoin_keypair.public_bytes()));
println!("private: 0x{}", hex::encode(bitcoin_keypair.private_bytes()));

println!("Ethereum wallet:");
let ethereum_keypair = enclave.get_ethereum_wallet_pair().unwrap();
println!("public : 0x{}", hex::encode(ethereum_keypair.public_bytes()));
println!("private: 0x{}", hex::encode(ethereum_keypair.private_bytes()));
} else {
println!("For options: use --help");
}
Expand Down
9 changes: 9 additions & 0 deletions bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use itc_parentchain::primitives::{
};
use itp_enclave_api::{enclave_base::EnclaveBase, sidechain::Sidechain, EnclaveResult};
use itp_settings::worker::MR_ENCLAVE_SIZE;
use itp_sgx_crypto::{ecdsa, schnorr};
use itp_storage::StorageProof;
use itp_types::{EnclaveFingerprint, ShardIdentifier};
use sgx_crypto_helper::rsa3072::Rsa3072PubKey;
Expand Down Expand Up @@ -88,6 +89,14 @@ impl EnclaveBase for EnclaveMock {
unreachable!()
}

fn get_bitcoin_wallet_pair(&self) -> EnclaveResult<schnorr::Pair> {
unreachable!()
}

fn get_ethereum_wallet_pair(&self) -> EnclaveResult<ecdsa::Pair> {
unreachable!()
}

fn get_fingerprint(&self) -> EnclaveResult<EnclaveFingerprint> {
Ok([1u8; MR_ENCLAVE_SIZE].into())
}
Expand Down

0 comments on commit 09c9022

Please sign in to comment.