Repository navigation
Worker OCall Abstraction, PoC - #293
Conversation
| // initialize o-call bridge | ||
| OCallBridge::initialize(Arc::new(OCallBridgeComponentFactoryImpl {})); | ||
|
|
There was a problem hiding this comment.
Here we initialize the component (i.e. global state) and inject the concrete implementation
|
A lot of the changes in the main file are just formatting changes, automatically applied by |
| pub struct RemoteAttestationOCallImpl { | ||
| // TODO as a member here we need the e-call API trait, so we can use it instead of making the e-call directly | ||
| } |
There was a problem hiding this comment.
This is the actual implementation of the remote attestation o-calls. This was extracted from the c-functions and turned into interfaces that only use Rust types. Translating from and to C-API types should be the responsibility of the FFI functions.
|
|
||
| pub struct Bridge {} | ||
|
|
||
| impl Bridge { |
There was a problem hiding this comment.
The Bridge is the static/global interface to inject concrete implementations (or rather the factories for them) - this is done at startup of the worker. On the other side, it is used by the o-call FFI to retrieve the state and forward calls to their respective implementation.
There was a problem hiding this comment.
Is there any reason you're not putting such comments directly into the code? I think (atleast for me) it would be really helpful to have the option to look up such comments also later on.
There was a problem hiding this comment.
Good input. This is also helpful for fellow sdk users.
There was a problem hiding this comment.
Yes, indeed, there probably should be more comments, especially in the future for all the public facing traits and functions.
I've neglected them in part because of laziness, but also because comments tend to go out of sync with the code VERY fast, and then they're more harmful than anything else. And here we're dealing with the beginning of some substantial refactoring, where everything is very volatile.. so far my excuse. Once we reach a more stable state, we should definitely do more documentation inside the code.
There was a problem hiding this comment.
My latest commit added some of the comments you (rightfully) requested
| let revocation_list: Vec<u8> = | ||
| unsafe { slice::from_raw_parts(p_sigrl, sigrl_len as usize).to_vec() }; | ||
|
|
||
| let report = unsafe { *p_report }; | ||
| let spid = unsafe { *p_spid }; | ||
| let quote_nonce = unsafe { *p_nonce }; |
There was a problem hiding this comment.
Translate parameters from C-API types to Rust types
| let quote = get_quote_result.2; | ||
|
|
||
| if quote.len() as u32 > maxlen { | ||
| return sgx_status_t::SGX_ERROR_FAAS_BUFFER_TOO_SHORT; | ||
| } | ||
|
|
||
| let quote_slice = unsafe { slice::from_raw_parts_mut(p_quote, quote.len()) }; | ||
| quote_slice.clone_from_slice(quote.as_slice()); | ||
|
|
||
| unsafe { | ||
| *p_qe_report = get_quote_result.1; | ||
| *p_quote_len = quote.len() as u32; | ||
| }; | ||
|
|
||
| get_quote_result.0 |
There was a problem hiding this comment.
Translate results back to the C-API
| fn init_quote(&self) -> (sgx_status_t, sgx_target_info_t, sgx_epid_group_id_t) { | ||
| // TODO this translation to unsafe C-API should be moved to the EnclaveApi / ECall API | ||
| let mut ti: sgx_target_info_t = sgx_target_info_t::default(); | ||
| let mut eg: sgx_epid_group_id_t = sgx_epid_group_id_t::default(); | ||
|
|
||
| unsafe { | ||
| let ret_status = sgx_init_quote( | ||
| &mut ti as *mut sgx_target_info_t, | ||
| &mut eg as *mut sgx_epid_group_id_t, | ||
| ); | ||
| (ret_status, ti, eg) | ||
| } | ||
| } |
There was a problem hiding this comment.
3 of the 4 methods for remote attestation basically just call back right into the enclave, using an e-call. Once we have the e-call API for this, these implementations should be moved to that API, making the implementation here very simple.
| impl OCallBridgeComponentFactory for OCallBridgeComponentFactoryImpl { | ||
| fn get_ra_api(&self) -> Arc<dyn RemoteAttestationOCall> { | ||
| Arc::new(RemoteAttestationOCallImpl {}) | ||
| } | ||
| } |
There was a problem hiding this comment.
Component factory, i.e. root for all ocall components. Once we're filling this up with more components for all the other ocalls, its usefulness will become apparent.
| #[test] | ||
| fn init_quote_sets_results() { | ||
| let mut ra_ocall_api_mock = MockRemoteAttestationOCall::new(); | ||
| ra_ocall_api_mock | ||
| .expect_init_quote() | ||
| .times(1) | ||
| .returning(|| (sgx_status_t::SGX_SUCCESS, dummy_target_info(), [8u8; 4])); | ||
|
|
||
| let mut ti: sgx_target_info_t = sgx_target_info_t::default(); | ||
| let mut eg: sgx_epid_group_id_t = sgx_epid_group_id_t::default(); | ||
|
|
||
| let ret_status = sgx_init_quote( | ||
| &mut ti as *mut sgx_target_info_t, | ||
| &mut eg as *mut sgx_epid_group_id_t, | ||
| Arc::new(ra_ocall_api_mock), | ||
| ); | ||
|
|
||
| assert_eq!(ret_status, sgx_status_t::SGX_SUCCESS); | ||
| assert_eq!(eg, [8u8; 4]); | ||
| } |
There was a problem hiding this comment.
Another simple test using the mocking framework to mock the RemoteAttestationOCall trait.
clangenb
left a comment
There was a problem hiding this comment.
Looks in general very good. In general, I don't see any design remarks that could stand in the way of our refactoring goal.
My remarks are only details and rather rust related.
e47ae3d to
bab40fe
Compare
clangenb
left a comment
There was a problem hiding this comment.
Cool. I like the new errors! My two comments are only a little nitpicking. :) Will approve anyhow.
There was a problem hiding this comment.
LGTM, though I haven't really looked at the overall structure. Leaving this task to @clangenb. :)
I'd really appreciate some more documentation though - especially when it gets as abstract as the bridge struct some reasoning comments (what is it used for, what's the original reasoning behind it...) would be really helpful.
| } | ||
| } | ||
|
|
||
| fn lookup_ipv4(host: &str, port: u16) -> Result<SocketAddr, String> { |
There was a problem hiding this comment.
Just as an information: This function, respective generally the transformation from a string and / or port to a SocketAdress is used for most ws applications, there's also one within the enclave
There was a problem hiding this comment.
Thanks, we should make sure then to share this code in an external crate, shared by both 👍
brenzi
left a comment
There was a problem hiding this comment.
it is unfortunate that this PR is mixed with cargo fmt changes. This makes reviewing painful. Actually I thought that we enforce fmt in CI anyway, but maybe that was dropped when moving to GH actions? We should enfore fmt in CI if we don't do so yet (excluding sgx_runtime, because parity doesn't use fmt)
I'm not yet sure that "bridge" is a good name. In blockchain, a bridge is usually something that allows cross-blockchain interaction. But, actually, we're bridging layer one with layer two somehow, so I'd leave it
|
I wouldn't mind renaming 'bridge' to something else, especially when that name is already reserved for another concept in the domain. It will never again be as simple as now to do the renaming.. What are the alternatives?
|
|
@mullefel You mentioned that you need to rebase before merging? there seem to be no conflicts, but let me know. I'd be ready to merge as soon as the Jenkins tests have passed Because we envision to implement an "integritee-bridge" in the future, I think we really should rename the "OcallBridge". |
|
I find 'Tunnel' an interesting suggestion - it's not something that I've found commonly used yet, but I think it could be a good fit in our case 👍 I will open an issue to re-name the bridges to 'tunnels'. I think it's less work to merge the PRs now and do the re-naming in a separate PR (instead of having to rebase a lot of conflicts because of the renaming) Edit: created issue #316 for this |
9c163f5 to
2ac8961
Compare
2ac8961 to
6065d03
Compare
Proof-of-concept for the abstraction of the OCall API in the untrusted worker. This will be a first step for #287 .
The entire OCall bridge component is still a module of the worker for now. In a later stage, this will be extracted to a separate crate. Implementation&behavior can be injected using the
Bridgestruct, that internally uses global static state.