Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why "C" calling convention? #5

Closed
burdges opened this issue Jan 11, 2017 · 5 comments
Closed

Why "C" calling convention? #5

burdges opened this issue Jan 11, 2017 · 5 comments

Comments

@burdges
Copy link
Contributor

burdges commented Jan 11, 2017

What does making all the functions extern "C" achieve? I suspect the code would be slightly simpler if one could use traits everywhere, but presumably you avoided doing that for good reason?

@burdges
Copy link
Contributor Author

burdges commented Jan 11, 2017

Just fyi, it appears rust checks for duplicate symbols on its side, but not from the C side, not that this matters much.

@burdges
Copy link
Contributor Author

burdges commented Jan 11, 2017

I worked around these #[no_mangle] extern "C" in #6 but it's still worth knowing if they actually matter. I guess maybe I'd need to look at you audit branch for that.

@burdges
Copy link
Contributor Author

burdges commented Jan 11, 2017

I see maybe! There are functions here that pass and return secret data by value, so the calling convention used must avoid placing them on the stack, as data on the stack cannot reliably be erased. Are these extern "C" functions guaranteed only to manipulate registers and avoid the stack except for the return address?

@valarauca
Copy link
Owner

valarauca commented Jan 12, 2017

Two reasons:

Rust/LLVM play it really fast and loose with the ABI. If they can avoid passing args they will (hard coded branches). If they can inline args (hard coded branches) they will. Also the LLVM will happily create multiple versions of the same functions for different call sites, and different ABI's it uses in multiple places.

Effectively. If you write normal code on top of the library you can accidentally opt-in an LLVM pass that may destroy some of the package's guarantees. So I'm attempting to opt-out of that behavior.

When I was reading the dis-assembly the C ABI helped me know which args were being introduced where.


I think long term the only way to fully avoid it is to compile the crate and re-expose it via the FFI. Which may avoid 99% of the issues as then that crate can be compiled at a lower optimization levels avoiding the need to write ASM for all the functions.

@burdges
Copy link
Contributor Author

burdges commented Jan 12, 2017

I donno if I completely understand, as I have not looked much at compiler output myself. I suppose however the C ABI dictates that ct_*_eq and ct_select_* do not use the stack, so using the C ABI cannot risk anything.

We should be careful about my changes on lines 255 and 360 in https://github.com/valarauca/consistenttime/pull/6/files I made those changes to increase test coverage, but they make your C ABI fn call a Rust ABI fn, albeit one that should be inlined. If anything goes wrong then maybe some #[inline(always)] directives on the trait and generic fns can solve the issue, maybe those would be smart anyways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants