Skip to content

Commit

Permalink
Add admin_proof_secret & contract_key_proof_secret
Browse files Browse the repository at this point in the history
Otherwise, both can be forged when sent into the enclave.
This is done using the same method as when we prove a callback_sig.
  • Loading branch information
assafmo committed Jun 20, 2023
1 parent f4da131 commit 0b7555a
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 23 deletions.
2 changes: 1 addition & 1 deletion cosmwasm/enclaves/ffi-types/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ pub enum MigrateResult {
/// A pointer to the output of the calculation
output: UserSpaceBuffer,
new_contract_key: [u8; 64],
proof: [u8; 32],
contract_key_proof: [u8; 32],
},
Failure {
/// The error that happened in the enclave
Expand Down
40 changes: 25 additions & 15 deletions cosmwasm/enclaves/shared/contract-engine/src/contract_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use cw_types_v010::encoding::Binary;
use cw_types_v010::types::CanonicalAddr;

use enclave_cosmos_types::types::{ContractCode, HandleType, SigInfo, VerifyParamsType};
use enclave_crypto::{sha_256, Ed25519PublicKey};
use enclave_crypto::{sha_256, Ed25519PublicKey, KEY_MANAGER};
use enclave_ffi_types::{Ctx, EnclaveError};
use log::*;

Expand Down Expand Up @@ -59,20 +59,30 @@ fn generate_admin_proof(admin: &[u8], contract_key: &[u8]) -> [u8; enclave_crypt
let mut data_to_hash = vec![];
data_to_hash.extend_from_slice(admin);
data_to_hash.extend_from_slice(contract_key);

let admin_proof_secret = KEY_MANAGER.get_admin_proof_secret().unwrap();

data_to_hash.extend_from_slice(admin_proof_secret.get());

sha_256(&data_to_hash)
}

fn generate_contract_key_proof(
address: &[u8],
contract_address: &[u8],
code_hash: &[u8],
prev_contract_key: &[u8],
new_contract_key: &[u8],
) -> [u8; enclave_crypto::HASH_SIZE] {
let mut data_to_hash = vec![];
data_to_hash.extend_from_slice(address);
data_to_hash.extend_from_slice(contract_address);
data_to_hash.extend_from_slice(code_hash);
data_to_hash.extend_from_slice(prev_contract_key);
data_to_hash.extend_from_slice(new_contract_key);

let contract_key_proof_secret = KEY_MANAGER.get_contract_key_proof_secret().unwrap();

data_to_hash.extend_from_slice(contract_key_proof_secret.get());

sha_256(&data_to_hash)
}

Expand Down Expand Up @@ -127,8 +137,6 @@ pub fn init(
&canonical_contract_address,
)?;

let admin_proof = generate_admin_proof(&canonical_admin_address.0 .0, &contract_key);

let parsed_sig_info: SigInfo = extract_sig_info(sig_info)?;

let secret_msg = SecretMessage::from_slice(msg)?;
Expand Down Expand Up @@ -220,6 +228,8 @@ pub fn init(

// todo: can move the key to somewhere in the output message if we want

let admin_proof = generate_admin_proof(&canonical_admin_address.0 .0, &contract_key);

Ok(InitSuccess {
output,
contract_key,
Expand Down Expand Up @@ -311,17 +321,10 @@ pub fn migrate(
let sneder_admin_proof = generate_admin_proof(&canonical_sender_address.0 .0, &og_contract_key);

if sneder_admin_proof != admin_proof {
error!("Failed to validate admin signature for migrate");
error!("Failed to validate sender as current admin for migrate");
return Err(EnclaveError::ValidationFailure);
}
debug!("validated migration proof successfully");

let contract_key_proof = generate_contract_key_proof(
&canonical_sender_address.0 .0,
&contract_code.hash(),
&og_contract_key,
&contract_key,
);
debug!("Validated migration proof successfully");

let parsed_sig_info: SigInfo = extract_sig_info(sig_info)?;

Expand Down Expand Up @@ -406,6 +409,13 @@ pub fn migrate(

// todo: can move the key to somewhere in the output message if we want

let contract_key_proof = generate_contract_key_proof(
&canonical_sender_address.0 .0,
&contract_code.hash(),
&og_contract_key,
&contract_key,
);

debug!(
"Migrate success: {:?}, {:?}",
contract_key, contract_key_proof
Expand All @@ -414,7 +424,7 @@ pub fn migrate(
Ok(MigrateSuccess {
output,
new_contract_key: contract_key,
proof: contract_key_proof,
contract_key_proof,
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub struct MigrateSuccess {
/// The output of the calculation
pub output: Vec<u8>,
pub new_contract_key: [u8; 64],
pub proof: [u8; 32],
pub contract_key_proof: [u8; 32],
}

pub fn result_migrate_success_to_result(
Expand All @@ -95,7 +95,7 @@ pub fn result_migrate_success_to_result(
Ok(MigrateSuccess {
output,
new_contract_key,
proof,
contract_key_proof,
}) => {
let user_buffer = unsafe {
let mut user_buffer = std::mem::MaybeUninit::<UserSpaceBuffer>::uninit();
Expand All @@ -114,7 +114,7 @@ pub fn result_migrate_success_to_result(
MigrateResult::Success {
output: user_buffer,
new_contract_key,
proof,
contract_key_proof,
}
}
Err(err) => MigrateResult::Failure { err },
Expand Down
2 changes: 2 additions & 0 deletions cosmwasm/enclaves/shared/crypto/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ pub const CONSENSUS_STATE_IKM_DERIVE_ORDER: u32 = 3;
pub const CONSENSUS_CALLBACK_SECRET_DERIVE_ORDER: u32 = 4;
pub const RANDOMNESS_ENCRYPTION_KEY_SECRET_DERIVE_ORDER: u32 = 5;
pub const INITIAL_RANDOMNESS_SEED_SECRET_DERIVE_ORDER: u32 = 6;
pub const ADMIN_PROOF_SECRET_DERIVE_ORDER: u32 = 7;
pub const CONTRACT_KEY_PROOF_SECRET_DERIVE_ORDER: u32 = 8;

pub const ENCRYPTED_KEY_MAGIC_BYTES: &[u8; 6] = b"secret";
pub const CONSENSUS_SEED_VERSION: u16 = 2;
Expand Down
44 changes: 44 additions & 0 deletions cosmwasm/enclaves/shared/crypto/src/key_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub struct Keychain {
#[cfg(feature = "random")]
pub initial_randomness_seed: Option<AESKey>,
registration_key: Option<KeyPair>,
admin_proof_secret: Option<AESKey>,
contract_key_proof_secret: Option<AESKey>,
}

#[derive(Clone, Copy, Default)]
Expand Down Expand Up @@ -89,6 +91,8 @@ impl Keychain {
initial_randomness_seed: None,
#[cfg(feature = "random")]
random_encryption_key: None,
admin_proof_secret: None,
contract_key_proof_secret: None,
};

let _ = x.generate_consensus_master_keys();
Expand Down Expand Up @@ -196,6 +200,20 @@ impl Keychain {
})
}

pub fn get_admin_proof_secret(&self) -> Result<AESKey, CryptoError> {
self.admin_proof_secret.ok_or_else(|| {
error!("Error accessing admin_proof_secret (does not exist, or was not initialized)");
CryptoError::ParsingError
})
}

pub fn get_contract_key_proof_secret(&self) -> Result<AESKey, CryptoError> {
self.contract_key_proof_secret.ok_or_else(|| {
error!("Error accessing contract_key_proof_secret (does not exist, or was not initialized)");
CryptoError::ParsingError
})
}

pub fn reseal_registration_key(&mut self) -> Result<(), EnclaveError> {
match Self::unseal_registration_key() {
Some(kp) => {
Expand Down Expand Up @@ -435,6 +453,32 @@ impl Keychain {
self.write_randomness_keys();
}

let admin_proof_secret = self
.consensus_seed
.unwrap()
.current
.derive_key_from_this(&ADMIN_PROOF_SECRET_DERIVE_ORDER.to_be_bytes());

self.admin_proof_secret = Some(admin_proof_secret);

trace!(
"initial_randomness_seed: {:?}",
hex::encode(admin_proof_secret.get())
);

let contract_key_proof_secret = self
.consensus_seed
.unwrap()
.current
.derive_key_from_this(&CONTRACT_KEY_PROOF_SECRET_DERIVE_ORDER.to_be_bytes());

self.contract_key_proof_secret = Some(contract_key_proof_secret);

trace!(
"initial_randomness_seed: {:?}",
hex::encode(contract_key_proof_secret.get())
);

Ok(())
}

Expand Down
8 changes: 4 additions & 4 deletions cosmwasm/packages/sgx-vm/src/wasmi/results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ pub fn migrate_result_to_vm_result(other: MigrateResult) -> VmResult<MigrateSucc
MigrateResult::Success {
output,
new_contract_key,
proof,
contract_key_proof,
} => Ok(MigrateSuccess {
output: unsafe { exports::recover_buffer(output) }.unwrap_or_else(Vec::new),
new_contract_key,
proof,
contract_key_proof,
}),
MigrateResult::Failure { err } => Err(err.into()),
}
Expand All @@ -55,13 +55,13 @@ pub struct MigrateSuccess {
/// A pointer to the output of the execution
output: Vec<u8>,
new_contract_key: [u8; 64],
proof: [u8; 32],
contract_key_proof: [u8; 32],
}

impl MigrateSuccess {
pub fn into_output(self) -> Vec<u8> {
let mut out_vec = self.new_contract_key.to_vec();
out_vec.extend_from_slice(&self.proof);
out_vec.extend_from_slice(&self.contract_key_proof);
out_vec.extend_from_slice(&self.output);
out_vec
}
Expand Down

0 comments on commit 0b7555a

Please sign in to comment.