Skip to content

Commit

Permalink
Fixed sealed export/import scheme
Browse files Browse the repository at this point in the history
  • Loading branch information
vlad committed Nov 14, 2024
1 parent dcd6f36 commit 4a319d6
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 45 deletions.
46 changes: 26 additions & 20 deletions cosmwasm/enclaves/execute/src/registration/offchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ use core::ptr::null;
use ed25519_dalek::{PublicKey, Signature};
use enclave_crypto::consts::{
make_sgx_secret_path, ATTESTATION_CERT_PATH, ATTESTATION_DCAP_PATH, COLLATERAL_DCAP_PATH,
CONSENSUS_SEED_VERSION, FILE_CERT_COMBINED, FILE_MIGRATION_CERT, FILE_MIGRATION_KDK,
CONSENSUS_SEED_VERSION, FILE_CERT_COMBINED, FILE_MIGRATION_CERT, FILE_MIGRATION_DATA,
INPUT_ENCRYPTED_SEED_SIZE, MIGRATION_CONSENSUS_PATH, PUBKEY_PATH, SEED_UPDATE_SAVE_PATH,
SIGNATURE_TYPE,
};
use enclave_crypto::{sha_256, AESKey, Ed25519PublicKey, KeyPair, SIVEncryptable, PUBLIC_KEY_SIZE};
use enclave_ffi_types::SINGLE_ENCRYPTED_SEED_SIZE;
use enclave_utils::key_manager::SEALING_KDK;
use enclave_utils::pointers::validate_mut_slice;
use enclave_utils::storage::{migrate_all_from_2_17, SELF_REPORT_BODY};
use enclave_utils::validator_set::ValidatorSetForHeight;
Expand Down Expand Up @@ -645,11 +644,11 @@ pub unsafe extern "C" fn ecall_migration_op(opcode: u32) -> sgx_types::sgx_statu
}
2 => {
println!("Export encrypted self sealing key to the next aurhorized enclave");
export_sealing_kdk()
export_sealed_data()
}
3 => {
println!("Import sealed data from the previous enclave");
import_sealing_kdk()
import_sealed_data()
}
4 => {
println!("Import sealed data from the legacy enclave");
Expand Down Expand Up @@ -880,7 +879,7 @@ fn is_export_approved(report: &sgx_report_body_t) -> bool {
false
}

fn export_sealing_kdk() -> sgx_status_t {
fn export_sealed_data() -> sgx_status_t {
let next_report = get_report_body(&make_sgx_secret_path(FILE_MIGRATION_CERT));
if !is_export_approved(&next_report) {
error!("Export sealing not authorized");
Expand All @@ -890,11 +889,15 @@ fn export_sealing_kdk() -> sgx_status_t {
let kp = Keychain::get_migration_keys();
let other_pub_k = &next_report.report_data.d[0..32].try_into().unwrap();
let aes_key = AESKey::new_from_slice(&kp.diffie_hellman(other_pub_k));
let sealing_kdk_encrypted = aes_key
.encrypt_siv(&SEALING_KDK as &sgx_types::sgx_key_128bit_t, None)

let mut data_plain = Vec::new();
KEY_MANAGER.serialize(&mut data_plain).unwrap();

let data_encrypted = aes_key
.encrypt_siv(&data_plain, None)
.unwrap();

let mut f_out = match File::create(make_sgx_secret_path(FILE_MIGRATION_KDK)) {
let mut f_out = match File::create(make_sgx_secret_path(FILE_MIGRATION_DATA)) {
Ok(f) => f,
Err(e) => {
error!("failed to create file {}", e);
Expand All @@ -903,14 +906,14 @@ fn export_sealing_kdk() -> sgx_status_t {
};

f_out.write_all(&kp.get_pubkey()).unwrap();
f_out.write_all(&sealing_kdk_encrypted).unwrap();
f_out.write_all(&data_encrypted).unwrap();

println!("Sealing key successfully exported");
println!("Sealed data successfully exported");
sgx_status_t::SGX_SUCCESS
}

fn import_sealing_kdk() -> sgx_status_t {
let mut f_in = match File::open(make_sgx_secret_path(FILE_MIGRATION_KDK)) {
fn import_sealed_data() -> sgx_status_t {
let mut f_in = match File::open(make_sgx_secret_path(FILE_MIGRATION_DATA)) {
Ok(f) => f,
Err(e) => {
error!("failed to open file {}", e);
Expand All @@ -921,27 +924,30 @@ fn import_sealing_kdk() -> sgx_status_t {
let mut other_pub_k: Ed25519PublicKey = Ed25519PublicKey::default();
f_in.read_exact(&mut other_pub_k).unwrap();

let mut sealing_kdk_encrypted = [0u8; 32];
f_in.read_exact(&mut sealing_kdk_encrypted).unwrap();
let mut data_encrypted = Vec::new();
f_in.read_to_end(&mut data_encrypted).unwrap();

let kp = Keychain::get_migration_keys();
let aes_key = AESKey::new_from_slice(&kp.diffie_hellman(&other_pub_k));
let sealing_kdk = match aes_key.decrypt_siv(&sealing_kdk_encrypted, None) {

let data_plain = match aes_key.decrypt_siv(&data_encrypted, None) {
Ok(res) => res,
Err(err) => {
error!("Can't decrypt sealing key: {}", err);
return sgx_status_t::SGX_ERROR_UNEXPECTED;
}
};

match Keychain::new_from_prev(sealing_kdk.as_slice().try_into().unwrap()) {
Some(key_manager) => {
let mut key_manager = Keychain::new_empty();

match key_manager.deserialize(&mut std::io::Cursor::new(data_plain)) {
Ok(_) => {
key_manager.save();
info!("Sealing data successfully imported");
sgx_status_t::SGX_SUCCESS
}
None => {
info!("Sealing data not found");
},
Err(err) => {
info!("Failed to read sealed data: {}", err);
sgx_status_t::SGX_ERROR_UNEXPECTED
}
}
Expand Down
2 changes: 1 addition & 1 deletion cosmwasm/enclaves/shared/crypto/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub const ATTESTATION_DCAP_SAVE_PATH: &str = "attestation_dcap.quote";
pub const COLLATERAL_DCAP_SAVE_PATH: &str = "attestation_dcap.collateral";
pub const FILE_CERT_COMBINED: &str = "attestation_combined.bin";
pub const FILE_MIGRATION_CERT: &str = "migration_report.bin";
pub const FILE_MIGRATION_KDK: &str = "migration_kdk.bin";
pub const FILE_MIGRATION_DATA: &str = "migration_data.bin";
pub const PUBKEY_SAVE_PATH: &str = "pubkey.bin";

pub const SEED_EXCH_KEY_SAVE_PATH: &str = "node-master-key.txt";
Expand Down
55 changes: 31 additions & 24 deletions cosmwasm/enclaves/shared/utils/src/key_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,18 @@ pub struct SeedsHolder<T> {
}

lazy_static! {
static ref SEALING_KDK: sgx_key_128bit_t = get_key_from_seed("seal.kdk".as_bytes());
pub static ref SEALED_DATA_PATH: String = make_sgx_secret_path(SEALED_FILE_UNITED);
pub static ref SEALING_KDK: sgx_key_128bit_t = get_key_from_seed("seal.kdk".as_bytes());
pub static ref KEY_MANAGER: Keychain = Keychain::new();
}

const KEYCHAIN_DATA_VER: u32 = 1;

#[allow(clippy::new_without_default)]
impl Keychain {
fn serialize(&self, writer: &mut dyn Write) -> std::io::Result<()> {
pub fn serialize(&self, writer: &mut dyn Write) -> std::io::Result<()> {
writer.write_all(&KEYCHAIN_DATA_VER.to_le_bytes())?;

if let Some(seeds) = self.consensus_seed {
writer.write_all(&[1_u8])?;
writer.write_all(seeds.genesis.as_slice())?;
Expand Down Expand Up @@ -95,7 +99,27 @@ impl Keychain {
Ok(())
}

fn deserialize(&mut self, reader: &mut dyn Read) -> std::io::Result<()> {
fn read_u32(reader: &mut dyn Read) -> std::io::Result<u32> {
let mut buf = [0u8; 4];
reader.read_exact(&mut buf)?;
Ok(u32::from_le_bytes(buf))
}

fn read_u64(reader: &mut dyn Read) -> std::io::Result<u64> {
let mut buf = [0u8; 8];
reader.read_exact(&mut buf)?;
Ok(u64::from_le_bytes(buf))
}

pub fn deserialize(&mut self, reader: &mut dyn Read) -> std::io::Result<()> {
let ver = Self::read_u32(reader)?;
if KEYCHAIN_DATA_VER != ver {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"unsupported ver",
));
}

let mut flag_bytes = [0u8; 1];

reader.read_exact(&mut flag_bytes)?;
Expand All @@ -118,12 +142,9 @@ impl Keychain {
self.registration_key = Some(KeyPair::from_sk(sk));
}

let mut buf_u64 = [0u8; 8];
reader.read_exact(&mut buf_u64)?;
self.validator_set_for_height.height = u64::from_le_bytes(buf_u64);
self.validator_set_for_height.height = Self::read_u64(reader)?;

reader.read_exact(&mut buf_u64)?;
let val_size = u64::from_le_bytes(buf_u64);
let val_size = Self::read_u64(reader)?;

self.validator_set_for_height.validator_set = vec![0u8; val_size as usize];
reader.read_exact(&mut self.validator_set_for_height.validator_set)?;
Expand All @@ -145,9 +166,9 @@ impl Keychain {
self.serialize(&mut file).unwrap();
}

fn load_ex(&mut self, key: &sgx_key_128bit_t) -> bool {
fn load(&mut self) -> bool {
let path: &str = &SEALED_DATA_PATH;
match SgxFile::open_ex(path, key) {
match SgxFile::open_ex(path, &SEALING_KDK) {
Ok(mut file) => {
println!("Sealed data opened");
self.deserialize(&mut file).unwrap();
Expand All @@ -160,10 +181,6 @@ impl Keychain {
}
}

fn load(&mut self) {
self.load_ex(&SEALING_KDK);
}

pub fn get_migration_keys() -> KeyPair {
let mut sk = Ed25519PrivateKey::default();
sk.get_mut()[..16].copy_from_slice(&get_key_from_seed("migrate.0.kdk".as_bytes()));
Expand Down Expand Up @@ -254,16 +271,6 @@ impl Keychain {
}
}

pub fn new_from_prev(key: &sgx_key_128bit_t) -> Option<Self> {
let mut x = Self::new_empty();
if x.load_ex(key) {
let _ = x.generate_consensus_master_keys();
Some(x)
} else {
None
}
}

pub fn get_validator_set_for_height() -> ValidatorSetForHeight {
// always re-read it
Keychain::new().validator_set_for_height
Expand Down

0 comments on commit 4a319d6

Please sign in to comment.