Skip to content

Commit 570fc26

Browse files
authored
Merge pull request #1642 from scrtlabs/dcap-05
Dcap 05
2 parents 65e732e + 88e17cc commit 570fc26

File tree

1 file changed

+152
-50
lines changed

1 file changed

+152
-50
lines changed

cosmwasm/enclaves/shared/utils/src/storage.rs

Lines changed: 152 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ use crate::results::UnwrapOrSgxErrorUnexpected;
22

33
use core::mem;
44
use core::ptr::null;
5+
use log::*;
56
use log::{error, info};
67
use std::io::{Read, Write};
78
use std::path::Path;
9+
use std::ptr;
810
use std::sgxfs::SgxFile;
911
use std::slice;
1012

@@ -71,6 +73,41 @@ pub struct FileMdPlain {
7173

7274
const FILE_MD_ENCRYPTED_DATA_SIZE: usize = 3072;
7375
const FILE_MD_ENCRYPTED_FILENAME_SIZE: usize = 260;
76+
const FILE_MD_ENCRYPTED_DATA_NODES: usize = 96;
77+
78+
#[repr(packed)]
79+
pub struct FileDataKeyAndMac {
80+
pub key: [u8; 16],
81+
pub gmac: [u8; 16],
82+
}
83+
84+
impl FileDataKeyAndMac {
85+
unsafe fn decrypt_once(
86+
&self,
87+
p_src: *const uint8_t,
88+
src_len: uint32_t,
89+
p_dst: *mut uint8_t,
90+
p_iv: &[u8; 12],
91+
) -> Result<(), sgx_status_t> {
92+
let res = sgx_rijndael128GCM_decrypt(
93+
&self.key,
94+
p_src,
95+
src_len,
96+
p_dst,
97+
p_iv.as_ptr(),
98+
12,
99+
null(),
100+
0,
101+
&self.gmac,
102+
);
103+
104+
if sgx_status_t::SGX_SUCCESS != res {
105+
return Err(res);
106+
}
107+
108+
Ok(())
109+
}
110+
}
74111

75112
#[repr(packed)]
76113
pub struct FileMdEncrypted {
@@ -81,8 +118,7 @@ pub struct FileMdEncrypted {
81118
pub mc_uuid: [u8; 16],
82119
pub mc_value: u32,
83120

84-
pub mht_key: [u8; 16],
85-
pub mht_gmac: [u8; 16],
121+
pub root_mht: FileDataKeyAndMac,
86122

87123
pub data: [u8; FILE_MD_ENCRYPTED_DATA_SIZE],
88124
}
@@ -94,29 +130,43 @@ pub struct FileMd {
94130
pub padding: [u8; 610],
95131
}
96132

133+
#[repr(packed)]
134+
pub struct FileMhtNode {
135+
pub data: [FileDataKeyAndMac; FILE_MD_ENCRYPTED_DATA_NODES],
136+
pub lower_nodes: [FileDataKeyAndMac; 32],
137+
}
138+
97139
pub fn unseal_file_from_2_17(
98140
s_path: &str,
99141
should_check_fname: bool,
100142
) -> Result<Vec<u8>, sgx_status_t> {
101143
let mut file = match File::open(s_path) {
102144
Ok(f) => f,
103-
Err(_) => {
104-
return Err(/*e*/ sgx_status_t::SGX_ERROR_UNEXPECTED);
145+
Err(e) => {
146+
warn!("Failed to open file: {}", e);
147+
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
105148
}
106149
};
107150

108151
let mut bytes = Vec::new();
109-
if file.read_to_end(&mut bytes).is_err() {
110-
return Err(/*e*/ sgx_status_t::SGX_ERROR_UNEXPECTED);
152+
if let Err(e) = file.read_to_end(&mut bytes) {
153+
warn!("Failed to read file: {}", e);
154+
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
111155
}
112156

113157
if bytes.len() < mem::size_of::<FileMd>() {
158+
warn!("file too small");
114159
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
115160
}
116161

117162
unsafe {
118163
let p_md = bytes.as_mut_ptr() as *const FileMd;
119164

165+
if (*p_md).plain.update_flag > 0 {
166+
warn!("file left in recovery mode, unsupported");
167+
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); // we don't support recovery
168+
}
169+
120170
let mut key_request = sgx_key_request_t {
121171
key_name: sgx_types::SGX_KEYSELECT_SEAL,
122172
key_policy: sgx_types::SGX_KEYPOLICY_MRSIGNER,
@@ -131,49 +181,39 @@ pub fn unseal_file_from_2_17(
131181
key_request.cpu_svn.svn = (*p_md).plain.cpu_svn;
132182
key_request.key_id.id = (*p_md).plain.key_id;
133183

134-
let mut cur_key: sgx_key_128bit_t = sgx_key_128bit_t::default();
184+
let mut cur_key_mac = FileDataKeyAndMac {
185+
key: sgx_key_128bit_t::default(),
186+
gmac: (*p_md).plain.meta_data_gmac,
187+
};
135188

136-
let mut st = sgx_get_key(&key_request, &mut cur_key);
137-
if sgx_status_t::SGX_SUCCESS != st {
138-
return Err(st);
189+
match sgx_get_key(&key_request, &mut cur_key_mac.key) {
190+
sgx_status_t::SGX_SUCCESS => {}
191+
err_code => {
192+
warn!("gen key failed");
193+
return Err(err_code);
194+
}
139195
}
140196

141197
let /* mut */ md_decr: FileMdEncrypted = FileMdEncrypted {
142198
clean_filename: [0; FILE_MD_ENCRYPTED_FILENAME_SIZE],
143199
size: 0,
144200
mc_uuid: [0; 16],
145201
mc_value: 0,
146-
mht_key: [0; 16],
147-
mht_gmac: [0; 16],
148-
149-
data: [0; 3072],
202+
root_mht: FileDataKeyAndMac{
203+
key: [0; 16],
204+
gmac: [0; 16],
205+
},
206+
data: [0; FILE_MD_ENCRYPTED_DATA_SIZE],
150207
};
151208

152209
let p_iv: [u8; 12] = [0; 12];
153210

154-
st = sgx_rijndael128GCM_decrypt(
155-
&cur_key,
211+
cur_key_mac.decrypt_once(
156212
std::ptr::addr_of!((*p_md).encr) as *const u8,
157213
mem::size_of::<FileMdEncrypted>() as u32,
158214
std::ptr::addr_of!(md_decr) as *mut uint8_t,
159-
p_iv.as_ptr() as *const u8,
160-
12,
161-
null(),
162-
0,
163-
&(*p_md).plain.meta_data_gmac,
164-
);
165-
166-
if sgx_status_t::SGX_SUCCESS != st {
167-
return Err(st);
168-
}
169-
170-
let ret_size = std::ptr::read_unaligned(std::ptr::addr_of!(md_decr.size)) as usize;
171-
if ret_size > FILE_MD_ENCRYPTED_DATA_SIZE {
172-
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
173-
}
174-
175-
bytes.resize(ret_size, 0);
176-
bytes.copy_from_slice(slice::from_raw_parts(md_decr.data.as_ptr(), ret_size));
215+
&p_iv,
216+
)?;
177217

178218
if should_check_fname {
179219
let raw_path = s_path.as_bytes();
@@ -204,6 +244,64 @@ pub fn unseal_file_from_2_17(
204244
return Err(sgx_status_t::SGX_ERROR_FILE_NAME_MISMATCH);
205245
}
206246
}
247+
248+
let ret_size = std::ptr::read_unaligned(std::ptr::addr_of!(md_decr.size)) as usize;
249+
250+
if ret_size <= FILE_MD_ENCRYPTED_DATA_SIZE {
251+
bytes.resize(ret_size, 0);
252+
bytes.copy_from_slice(slice::from_raw_parts(md_decr.data.as_ptr(), ret_size));
253+
} else {
254+
let node_size = mem::size_of::<FileMd>(); // 4K
255+
256+
let num_nodes = (ret_size - FILE_MD_ENCRYPTED_DATA_SIZE + node_size - 1) / node_size;
257+
if num_nodes > FILE_MD_ENCRYPTED_DATA_NODES {
258+
warn!("too many nodes, indirect files not supported");
259+
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
260+
}
261+
262+
let size_required = mem::size_of::<FileMd>() + node_size * (num_nodes + 1);
263+
if bytes.len() < size_required {
264+
warn!("file too short");
265+
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
266+
}
267+
268+
let mut bytes_src = bytes;
269+
bytes = Vec::new();
270+
bytes.resize(FILE_MD_ENCRYPTED_DATA_SIZE + node_size * num_nodes, 7); // allocate with padding
271+
272+
let mut offs_dst = FILE_MD_ENCRYPTED_DATA_SIZE;
273+
274+
ptr::copy_nonoverlapping(md_decr.data.as_ptr(), bytes.as_mut_ptr(), offs_dst);
275+
276+
// Decode mht node
277+
let p_mht_node =
278+
bytes_src.as_mut_ptr().add(mem::size_of::<FileMd>()) as *mut FileMhtNode;
279+
280+
md_decr.root_mht.decrypt_once(
281+
p_mht_node as *const u8,
282+
mem::size_of::<FileMhtNode>() as u32,
283+
p_mht_node as *mut uint8_t,
284+
&p_iv,
285+
)?;
286+
287+
let mut offs_src = mem::size_of::<FileMd>() + node_size;
288+
289+
for i_node in 0..num_nodes {
290+
let keys = &(*p_mht_node).data[i_node];
291+
292+
keys.decrypt_once(
293+
bytes_src.as_ptr().add(offs_src),
294+
node_size as u32,
295+
bytes.as_mut_ptr().add(offs_dst),
296+
&p_iv,
297+
)?;
298+
299+
offs_src += node_size;
300+
offs_dst += node_size;
301+
}
302+
303+
bytes.resize(ret_size, 0); // truncate the padding
304+
}
207305
};
208306

209307
Ok(bytes)
@@ -214,26 +312,30 @@ pub fn migrate_file_from_2_17_safe(
214312
should_check_fname: bool,
215313
) -> Result<(), sgx_status_t> {
216314
if Path::new(s_path).exists() {
217-
let data = match unseal_file_from_2_17(s_path, should_check_fname) {
218-
Ok(x) => x,
219-
Err(e) => {
220-
error!("Couldn't unseal file {}, {}", s_path, e);
221-
return Err(e);
315+
if SgxFile::open(s_path).is_ok() {
316+
info!("File {} is already converted", s_path);
317+
} else {
318+
let data = match unseal_file_from_2_17(s_path, should_check_fname) {
319+
Ok(x) => x,
320+
Err(e) => {
321+
error!("Couldn't unseal file {}, {}", s_path, e);
322+
return Err(e);
323+
}
324+
};
325+
326+
let s_path_bkp = s_path.to_string() + ".bkp";
327+
if let Err(e) = fs::copy(s_path, &s_path_bkp) {
328+
error!("Couldn't backup {} into {}, {}", s_path, s_path_bkp, e);
329+
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
222330
}
223-
};
224331

225-
let s_path_bkp = s_path.to_string() + ".bkp";
226-
if let Err(e) = fs::copy(s_path, &s_path_bkp) {
227-
error!("Couldn't backup {} into {}, {}", s_path, s_path_bkp, e);
228-
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
229-
}
332+
if let Err(e) = seal(data.as_slice(), s_path) {
333+
error!("Couldn't RE-seal file {}, {}", s_path, e);
334+
return Err(e);
335+
}
230336

231-
if let Err(e) = seal(data.as_slice(), s_path) {
232-
error!("Couldn't RE-seal file {}, {}", s_path, e);
233-
return Err(e);
337+
info!("File {} successfully RE-sealed", s_path);
234338
}
235-
236-
info!("File {} successfully RE-sealed", s_path);
237339
} else {
238340
info!("File {} doesn't exist, skipping", s_path);
239341
}

0 commit comments

Comments
 (0)