Page MenuHomePhorge

From libolm to vodozemac
Updated 32 Days AgoPublic

This is currently a work-in-progress.

This document aims to provide you an overview of how to port your Matrix application from libolm to vodozemac.

Definitions

We will be using the following definitions in the document:

  • The E2EE library means either libolm or vodozemac.
  • The application means any code that uses the E2EE library, which may be another library.
  • The user means anyone who interacts with the application in any way other than writing code.

Differences

vodozemac-bindings has a C++ public API, as opposed to the C API of libolm. There are a couple of differences in the API:

  • Memory allocations are managed by vodozemac, not by the application.
  • You can no longer pass random data into the E2EE library, as vodozemac embeds the rust's random generator in it. This renders the "test vectors" in the spec effectively useless.
  • You have to have exceptions support in your compiler. This is a limitation of cxx.rs , which is used to generate the bindings. See https://github.com/dtolnay/cxx/issues/1052 for more information. This might change later.
  • Pickle keys are now 32 bytes, instead of any string.

Overview of vodozemac-bindings

Everything is in the vodozemac namespace. A function may throw an exception if it returns anything other than Result<T> in rust code. In the generated C++ header, it corresponds to the noexcept specifier. If a function is declared noexcept, it does not throw an exception; otherwise, it may.

You can use the following code to check for exceptions:

template<class Func>
auto checkVodozemacError(Func &&func) -> std::optional<std::invoke_result_t<Func>>
{
    try {
        return std::forward<Func>(func)();
    } catch (const std::exception &e) {
        return std::nullopt;
    }
}

Converting from libolm

vodozemac-bindings provides function to convert data from libolm pickle format. They are called *_from_libolm_pickle and takes two arguments: the first one is the pickle data, as rust::Str, the other being the pickle key, as rust::Slice<const unsigned char>. rust::Str can be directly converted from a std::string, while rust::Slice needs some work, for example:

auto session = checkVodozemacError([&]() {
    return vodozemac::megolm::inbound_group_session_from_libolm_pickle(pickleData, rust::Slice<const unsigned char>(pickleKey.data(), pickleKey.size()));
});

Changes to first inbound olm message

One important change in vodozemac is that when you create an inbound olm session from an encrypted message, you instantly get the decrypted content as return, and decrypt() will NOT work for the first message.

auto res = checkVodozemacError([&]() {
    auto identityKey = vodozemac::types::curve_key_from_base64(rust::Str(theirIdentityKey));
    auto msg = vodozemac::olm::olm_message_from_parts(vodozemac::olm::OlmMessageParts{
            0, // pre-key message
            message,
        });
    return account->create_inbound_session(
        *identityKey,
        *msg
    );
});
if (res.has_value()) {
    session = std::move(res->session);
    firstDecrypted = std::string(res->plaintext.begin(), res->plaintext.end());
}

Sample code

The commits referenced in https://iron.lily-is.land/T125 provides a sample code to migrate from libolm to vodozemac.

Last Author
tusooa
Last Edited
Aug 14 2024, 5:39 PM

Event Timeline

tusooa published a new version of this document.