Skip to content

Commit

Permalink
Merge pull request #537 from LayerXcom/feature/enclave_key_cmd
Browse files Browse the repository at this point in the history
Enclave鍵を用いた命令の暗号化実装
  • Loading branch information
osuketh authored Mar 31, 2021
2 parents 8b7be07 + f1a2872 commit 4663776
Show file tree
Hide file tree
Showing 26 changed files with 995 additions and 857 deletions.
6 changes: 3 additions & 3 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ ACCOUNT_INDEX=0
PASSWORD=anonify0101
EVENT_LIMIT=100
UNLOCK_DURATION=60
ANONIFY_ABI_PATH=contract-build/AnonifyWithTreeKem.abi
ANONIFY_BIN_PATH=contract-build/AnonifyWithTreeKem.bin
ANONIFY_ABI_PATH=contract-build/AnonifyWithEnclaveKey.abi
ANONIFY_BIN_PATH=contract-build/AnonifyWithEnclaveKey.bin
FACTORY_ABI_PATH=contract-build/DeployAnonify.abi
FACTORY_BIN_PATH=contract-build/DeployAnonify.bin
FACTORY_CONTRACT_ADDRESS=
Expand All @@ -45,7 +45,7 @@ RETRY_DELAY_MILLS=100
# MY_ROSTER_IDX must unique identifier in your group
MY_ROSTER_IDX=0
MAX_ROSTER_IDX=2
PATH_SECRETS_DIR=.anonify/pathsecrets
CMD_DEC_SECRET_DIR=.anonify/cmd-dec-secret


### MISC ###
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ services:
PASSWORD: ${PASSWORD}
REQUEST_RETRIES: ${REQUEST_RETRIES}
RETRY_DELAY_MILLS: ${RETRY_DELAY_MILLS}
PATH_SECRETS_DIR: ${PATH_SECRETS_DIR}
CMD_DEC_SECRET_DIR: ${CMD_DEC_SECRET_DIR}
IAS_ROOT_CERT_PATH: ${IAS_ROOT_CERT_PATH}
EVENT_LIMIT: ${EVENT_LIMIT}
UNLOCK_DURATION: ${UNLOCK_DURATION}
Expand Down
6 changes: 2 additions & 4 deletions ethereum/contracts/AnonifyWithEnclaveKey.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,11 @@ contract AnonifyWithEnclaveKey is ReportHandle {
function storeCommand(
bytes memory _newCiphertext,
bytes memory _enclaveSig,
uint32 _rosterIdx,
uint32 _generation,
uint32 _epoch
uint32 _rosterIdx
) public {
address verifyingKey =
Secp256k1.recover(
sha256(abi.encodePacked(_newCiphertext, _rosterIdx, _generation, _epoch)),
sha256(abi.encodePacked(_newCiphertext, _rosterIdx)),
_enclaveSig
);
require(
Expand Down
12 changes: 10 additions & 2 deletions example/erc20/enclave/src/ecalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ register_ecall!(
(FETCH_HANDSHAKE_TREEKEM_CMD, HandshakeReceiver),
// Get current state of the user represented the given public key from enclave memory database.
(GET_STATE_CMD, GetState<Ed25519ChallengeResponse>),
(JOIN_GROUP_TREEKEM_CMD, JoinGroupWithTreeKem),
(JOIN_GROUP_ENCLAVE_KEY_CMD, JoinGroupWithEnclaveKey),
(SEND_HANDSHAKE_TREEKEM_CMD, HandshakeSender),
(
REGISTER_NOTIFICATION_CMD,
Expand All @@ -38,6 +38,14 @@ register_ecall!(
GET_USER_COUNTER_CMD,
GetUserCounter<Ed25519ChallengeResponse>
),
(
SEND_COMMAND_ENCLAVE_KEY_CMD,
CommandByEnclaveKeySender<Ed25519ChallengeResponse>
),
(
FETCH_CIPHERTEXT_ENCLAVE_KEY_CMD,
CommandByEnclaveKeyReceiver<Ed25519ChallengeResponse>
),
);

#[cfg(feature = "backup-enable")]
Expand All @@ -59,7 +67,7 @@ register_ecall!(
(FETCH_HANDSHAKE_TREEKEM_CMD, HandshakeReceiver),
// Get current state of the user represented the given public key from enclave memory database.
(GET_STATE_CMD, GetState<Ed25519ChallengeResponse>),
(JOIN_GROUP_TREEKEM_CMD, JoinGroupWithTreeKem),
(JOIN_GROUP_ENCLAVE_KEY_CMD, JoinGroupWithEnclaveKey),
(SEND_HANDSHAKE_TREEKEM_CMD, HandshakeSender),
(
REGISTER_NOTIFICATION_CMD,
Expand Down
4 changes: 2 additions & 2 deletions frame/config/src/envs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ lazy_static! {
.parse::<u64>()
.unwrap()
};
pub static ref PATH_SECRETS_DIR: String =
env::var("PATH_SECRETS_DIR").unwrap_or(".anonify/pathsecrets".to_string());
pub static ref CMD_DEC_SECRET_DIR: String =
env::var("CMD_DEC_SECRET_DIR").unwrap_or(".anonify/cmd-dec-secret".to_string());
pub static ref PJ_ROOT_DIR: PathBuf = {
let pj_name = env::var("PJ_NAME").unwrap_or("anonify".to_string());
let mut current_dir = env::current_dir().unwrap();
Expand Down
20 changes: 8 additions & 12 deletions frame/sodium/src/store_dec_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ use frame_config::PJ_ROOT_DIR;
use serde_json_sgx as serde_json;
use tracing::info;

const DEC_KEY_FILE_NAME: &str = "enclave_decryption_key";

#[derive(Debug, Clone, Default)]
pub struct StoreEnclaveDecryptionKey {
local_dir_path: PathBuf,
Expand All @@ -24,21 +22,16 @@ impl StoreEnclaveDecryptionKey {
StoreEnclaveDecryptionKey { local_dir_path }
}

pub fn create_dir_all<P: AsRef<Path>>(mut self, path: P) -> Result<Self> {
self.local_dir_path.push(path);
fs::create_dir_all(&self.local_dir_path)?;
Ok(self)
}

pub fn local_dir_path(&self) -> &Path {
&self.local_dir_path
}

pub fn save_to_local_filesystem(
pub fn save_to_local_filesystem<P: AsRef<Path>>(
&self,
sealed_dec_key: &SealedEnclaveDecryptionKey<'_>,
file_name: P,
) -> Result<()> {
let file_path = self.local_dir_path.join(DEC_KEY_FILE_NAME);
let file_path = self.local_dir_path.join(file_name);
info!(
"Saving a sealed enclave decryption key to the path: {:?}",
file_path
Expand All @@ -51,8 +44,11 @@ impl StoreEnclaveDecryptionKey {
Ok(())
}

pub fn load_from_local_filesystem(&self) -> Result<UnsealedEnclaveDecryptionKey> {
let file_path = self.local_dir_path.join(DEC_KEY_FILE_NAME);
pub fn load_from_local_filesystem<P: AsRef<Path>>(
&self,
file_name: P,
) -> Result<UnsealedEnclaveDecryptionKey> {
let file_path = self.local_dir_path.join(file_name);
info!(
"Loading a sealed enclave decryption key from the path: {:?}",
file_path
Expand Down
6 changes: 3 additions & 3 deletions frame/treekem/src/store_path_secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ pub struct StorePathSecrets {
}

impl StorePathSecrets {
pub fn new<P: AsRef<Path>>(path_secrets_dir: P) -> Self {
let local_dir_path = (*PJ_ROOT_DIR).to_path_buf().join(path_secrets_dir);
fs::create_dir_all(&local_dir_path).expect("Failed to create PATH_SECRETS_DIR");
pub fn new<P: AsRef<Path>>(cmd_dec_secret_dir: P) -> Self {
let local_dir_path = (*PJ_ROOT_DIR).to_path_buf().join(cmd_dec_secret_dir);
fs::create_dir_all(&local_dir_path).expect("Failed to create CMD_DEC_SECRET_DIR");
StorePathSecrets { local_dir_path }
}

Expand Down
4 changes: 2 additions & 2 deletions frame/treekem/src/test_funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::group_state::GroupState;
use crate::handshake::{Handshake, PathSecretKVS, PathSecretSource};
use crate::{PathSecret, StorePathSecrets};
use anyhow::anyhow;
use frame_config::PATH_SECRETS_DIR;
use frame_config::CMD_DEC_SECRET_DIR;
use rand_core::SeedableRng;
use std::env;

Expand All @@ -27,7 +27,7 @@ pub fn do_handshake_three_party(
.parse::<u32>()
.unwrap();
let (handshake, _) = my_group.create_handshake(source).unwrap();
let store_path_secrets = StorePathSecrets::new(&*PATH_SECRETS_DIR);
let store_path_secrets = StorePathSecrets::new(&*CMD_DEC_SECRET_DIR);

let my_keychain = my_group
.process_handshake(
Expand Down
22 changes: 15 additions & 7 deletions modules/anonify-ecall-types/src/ciphertexts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,41 @@ impl Default for CommandCiphertext {
#[serde(crate = "crate::serde")]
pub struct EnclaveKeyCiphertext {
pub encrypted_state: SodiumCiphertext,
roster_idx: u32,
}

impl fmt::Debug for EnclaveKeyCiphertext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"EnclaveKeyCiphertext {{ encrypted_state: 0x{} }}",
hex::encode(self.encode())
"EnclaveKeyCiphertext {{ encrypted_state: 0x{}, roster_idx: {:?} }}",
hex::encode(self.encode()),
self.roster_idx()
)
}
}

impl EnclaveKeyCiphertext {
pub fn new(encrypted_state: SodiumCiphertext) -> Self {
EnclaveKeyCiphertext { encrypted_state }
pub fn new(encrypted_state: SodiumCiphertext, roster_idx: u32) -> Self {
EnclaveKeyCiphertext {
encrypted_state,
roster_idx,
}
}

pub fn decode(bytes: &[u8]) -> crate::localstd::result::Result<Self, Box<bincode::ErrorKind>> {
let encrypted_state = SodiumCiphertext::decode(bytes)?;
Ok(Self { encrypted_state })
bincode::deserialize(bytes)
}

pub fn encode(&self) -> Vec<u8> {
self.encrypted_state.encode()
bincode::serialize(&self).unwrap() //must not fail
}

pub fn encrypted_state(&self) -> &SodiumCiphertext {
&self.encrypted_state
}

pub fn roster_idx(&self) -> u32 {
self.roster_idx
}
}
1 change: 0 additions & 1 deletion modules/anonify-ecall-types/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,6 @@ pub mod output {
report: Vec<u8>,
#[serde(with = "serde_bytes")]
report_sig: Vec<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
handshake: Option<Vec<u8>>,
mrenclave_ver: u32,
roster_idx: u32,
Expand Down
10 changes: 5 additions & 5 deletions modules/anonify-enclave/src/commands/enclave_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,16 @@ where
R: RuntimeExecutor<C, S = StateType>,
C: ContextOps<S = StateType> + Clone,
{
let my_roster_idx = enclave_context.my_roster_idx();
let my_roster_idx = enclave_context.my_roster_idx() as u32;
let pubkey = enclave_context.enclave_encryption_key()?;
let my_account_id = self.command_plaintext.access_policy().into_account_id();

let mut csprng = SgxRng::new()?;
let ciphertext = CommandExecutor::<R, C, AP>::new(my_account_id, self.command_plaintext)?
.encrypt_with_enclave_key(&mut csprng, pubkey, max_mem_size)?;
let ciphertext =
CommandExecutor::<R, C, AP>::new(my_account_id, self.command_plaintext)?
.encrypt_with_enclave_key(&mut csprng, pubkey, max_mem_size, my_roster_idx)?;

let msg =
Sha256::hash_for_attested_enclave_key_tx(&ciphertext.encode(), my_roster_idx as u32);
let msg = Sha256::hash_for_attested_enclave_key_tx(&ciphertext.encode(), my_roster_idx);
let enclave_sig = enclave_context.sign(msg.as_bytes())?;
let command_output = output::Command::new(
CommandCiphertext::EnclaveKey(ciphertext),
Expand Down
3 changes: 2 additions & 1 deletion modules/anonify-enclave/src/commands/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ where
csprng: &mut RNG,
pubkey: SodiumPubKey,
max_mem_size: usize,
roster_idx: u32,
) -> Result<EnclaveKeyCiphertext> {
let mut buf = bincode::serialize(&self).unwrap(); // must not fail
Self::append_padding(&mut buf, max_mem_size);
let encrypted_state = SodiumCiphertext::encrypt(csprng, &pubkey, &buf)?;
Ok(EnclaveKeyCiphertext::new(encrypted_state))
Ok(EnclaveKeyCiphertext::new(encrypted_state, roster_idx))
}

pub fn decode(bytes: &[u8]) -> Result<Self> {
Expand Down
4 changes: 2 additions & 2 deletions modules/anonify-enclave/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use frame_common::{
};
#[cfg(feature = "backup-enable")]
use frame_config::KEY_VAULT_ENCLAVE_MEASUREMENT;
use frame_config::{ANONIFY_PARAMS_DIR, IAS_ROOT_CERT, PATH_SECRETS_DIR};
use frame_config::{ANONIFY_PARAMS_DIR, IAS_ROOT_CERT, CMD_DEC_SECRET_DIR};
use frame_enclave::EnclaveEngine;
#[cfg(feature = "backup-enable")]
use frame_mra_tls::{
Expand Down Expand Up @@ -368,7 +368,7 @@ impl AnonifyEnclaveContext {
)
};

let store_path_secrets = StorePathSecrets::new(&*PATH_SECRETS_DIR);
let store_path_secrets = StorePathSecrets::new(&*CMD_DEC_SECRET_DIR);
let store_enclave_dec_key = StoreEnclaveDecryptionKey::new(&*ANONIFY_PARAMS_DIR);
let state_counter = Arc::new(SgxRwLock::new(StateCounter::default()));

Expand Down
5 changes: 3 additions & 2 deletions modules/anonify-enclave/src/enclave_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const HASHED_PUBKEY_SIZE: usize = 20;
const ENCLAVE_ENCRYPTION_KEY_SIZE: usize = SODIUM_PUBLIC_KEY_SIZE;
const FILLED_REPORT_DATA_SIZE: usize = HASHED_PUBKEY_SIZE + ENCLAVE_ENCRYPTION_KEY_SIZE;
const REPORT_DATA_SIZE: usize = 64;
const DEC_KEY_FILE_NAME: &str = "sr_enclave_decryption_key";

#[derive(Debug, Clone, Default)]
pub struct EncryptionKeyGetter;
Expand Down Expand Up @@ -79,7 +80,7 @@ impl EnclaveKey {
store_dec_key: &StoreEnclaveDecryptionKey,
) -> Result<Self> {
let decryption_privkey = store_dec_key
.load_from_local_filesystem()?
.load_from_local_filesystem(DEC_KEY_FILE_NAME)?
.into_sodium_priv_key()?;

self.decryption_privkey = Some(decryption_privkey);
Expand Down Expand Up @@ -119,7 +120,7 @@ impl EnclaveKey {
let sealed =
SealedEnclaveDecryptionKey::decode(&encoded).map_err(|e| anyhow!("{:?}", e))?;
store_dec_key
.save_to_local_filesystem(&sealed)
.save_to_local_filesystem(&sealed, DEC_KEY_FILE_NAME)
.map_err(Into::into)
}

Expand Down
5 changes: 4 additions & 1 deletion modules/anonify-enclave/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ mod notify;
pub mod workflow {
#[cfg(feature = "backup-enable")]
pub use crate::backup::{PathSecretBackupper, PathSecretRecoverer};
pub use crate::commands::treekem::{CommandByTreeKemReceiver, CommandByTreeKemSender};
pub use crate::commands::{
enclave_key::{CommandByEnclaveKeyReceiver, CommandByEnclaveKeySender},
treekem::{CommandByTreeKemReceiver, CommandByTreeKemSender},
};
pub use crate::context::{GetState, GetUserCounter, ReportRegistration};
pub use crate::enclave_key::EncryptionKeyGetter;
pub use crate::handshake::{HandshakeReceiver, HandshakeSender};
Expand Down
4 changes: 2 additions & 2 deletions modules/anonify-eth-driver/src/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl Dispatcher {
signer: Address,
gas: u64,
fetch_ciphertext_ecall_cmd: u32,
fetch_handshake_ecalll_cmd: u32,
fetch_handshake_ecalll_cmd: Option<u32>,
join_group_ecall_cmd: u32,
) -> Result<Self> {
let this = self.clone();
Expand Down Expand Up @@ -156,7 +156,7 @@ impl Dispatcher {
pub async fn fetch_events(
&self,
fetch_ciphertext_ecall_cmd: u32,
fetch_handshake_ecall_cmd: u32,
fetch_handshake_ecall_cmd: Option<u32>,
) -> Result<Option<Vec<serde_json::Value>>> {
let inner = self.inner.read();
let eid = inner.enclave_id;
Expand Down
30 changes: 27 additions & 3 deletions modules/anonify-eth-driver/src/eth/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,22 @@ impl Web3Contract {
)
.await
.map_err(Into::into),
None => unimplemented!(),
None => self
.contract
.call_with_confirmations(
method,
(
report,
report_sig,
ecall_output.mrenclave_ver(),
ecall_output.roster_idx(),
),
output.signer,
Options::with(|opt| opt.gas = Some(gas.into())),
confirmations,
)
.await
.map_err(Into::into),
}
}

Expand Down Expand Up @@ -109,7 +124,6 @@ impl Web3Contract {
.map_err(Into::into)
}

// TODO: treekem
pub async fn send_command(&self, output: host_output::Command) -> Result<H256> {
let ecall_output = output
.ecall_output
Expand All @@ -136,7 +150,16 @@ impl Web3Contract {
)
.await
.map_err(Into::into),
_ => return Err(HostError::InvalidCiphertextError),
CommandCiphertext::EnclaveKey(ciphertext) => self
.contract
.call(
"storeCommand",
(ciphertext.encode(), enclave_sig, ciphertext.roster_idx()),
output.signer,
Options::with(|opt| opt.gas = Some(gas.into())),
)
.await
.map_err(Into::into),
}
}

Expand Down Expand Up @@ -181,6 +204,7 @@ impl Web3Contract {
topic0: Topic::OneOf(vec![
*STORE_TREEKEM_CIPHERTEXT_EVENT,
*STORE_TREEKEM_HANDSHAKE_EVENT,
*STORE_ENCLAVE_KEY_CIPHERTEXT_EVENT,
]),
topic1: Topic::Any,
topic2: Topic::Any,
Expand Down
Loading

0 comments on commit 4663776

Please sign in to comment.