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

[uniffi] Make mls-rs-crypto-openssl optional #157

Closed
wants to merge 1 commit into from

Conversation

mgeisler
Copy link
Contributor

@mgeisler mgeisler commented May 8, 2024

Issues:

Addresses #81.

Description of changes:

For Android, we will be using a crypto provider based on BoringSSL. It is therefore important that mls-rs-uniffi becomes agnostic to the crypto provider.

This PR handles this very simply: by requiring two things:

  • the user sets a Cargo feature to depend on the right crypto provider implementation,
  • that the crypto provider has a suitable new() method that can be used to instantiate it.

fail because the CryptoProvider trait has an associated type, which I cannot specify at this point.

Call-outs:

A better alternative would be to make the choice of crypto provider dynamic via a trait. Unfortunately, I don’t think this is supported with UniFFI because it doesn’t support associated types in exported traits and because it also doesn’t support generic exported types.

Making a single non-generic type which uses

struct CryptoProviderAdapter {
    crypto_provider: Box<dyn CryptoProvider>
}

doesn't compile because I need to specify the CipherSuiteProvider associated type. I don't know how I can do this in a non-generic way?

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT license.

For Android, we will be using a crypto provider based on BoringSSL. It
is therefore important that mls-rs-uniffi becomes agnostic to the
crypto provider.

This PR handles this very simply: by requiring two things:

- the user sets a Cargo feature to depend on the right crypto provider
  implementation,
- that the crypto provider has a suitable `new()` method that can be
  used to instantiate it.

A better alternative would be to make the choice of crypto provider
dynamic via a trait. Unfortunately, I don’t think this is supported
with UniFFI because it doesn’t support associated types in exported
traits and because it also doesn’t support generic exported types.

Making a single non-generic type which uses

```rust
struct CryptoProviderAdapter {
    crypto_provider: Box<dyn CryptoProvider>
}
```

fail because the `CryptoProvider` trait has an associated type, which
I cannot specify at this point.
@mgeisler mgeisler requested a review from a team as a code owner May 8, 2024 14:29
Comment on lines +58 to +63
#[cfg(not(any(feature = "openssl")))]
compile_error!(
"The crypto provider must be set by enabling exactly one of the \
following Cargo features: [\"openssl\"]."
);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it work to make it like this?

#[cfg(not(any(feature = "openssl")))]
pub type UniFFICryptoProvider = mls_rs::client_builder::Missing;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Marta, yes, we could use that type by default — when I tried it out, I ended up with more complex error messages, not fewer like I had hoped 😅

But it would be nice to use it for consistency.

Comment on lines +64 to +66
#[cfg(feature = "openssl")]
pub type UniFFICryptoProvider = mls_rs_crypto_openssl::OpensslCryptoProvider;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we create another feature "boringssl", we won't be able to have UniFFICryptoProvider defined twice, but features should be additive. Can we achieve additive features by defining #[cfg(feature = "openssl")] UniFFIConfigOpenssl = ... and #[cfg(feature = "boringssl")] UniFFIConfigBoringssl = ...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we create another feature "boringssl", we won't be able to have UniFFICryptoProvider defined twice, but features should be additive.

Yes, ideally... I was going to guard against having multiple features enabled by letting the build fail with compile_fail! like you saw above. It's not great, but I don't know of a way to make the crypto provider dynamic at runtime.

What we need is

  • a non-generic struct which holds a mls_rs::Client inside it
  • the mls_rs::Client value should be able to hold different CryptoProviders, implying that we should have a CryptoProviderWrapper type which impl CryptoProvider and which holds a Box<dyn CryptoProvider>

So I'm looking for a way to do

struct CryptoProviderWrapper {
    crypto_provider: Box<dyn CryptoProvider>,
}

However, this doesn't compile because I need to specify the CipherSuiteProvider associated type. I don't know how I can do this in a non-generic way?

@mgeisler
Copy link
Contributor Author

Let me close this again, we're now looking at using Diplomat instead of UniFFI.

@mgeisler mgeisler closed this Aug 22, 2024
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

Successfully merging this pull request may close these issues.

2 participants