This post serves as documentation for my future self and others, and might be useful for people apart from Whisperfish devs. RingRTC is the library that Signal uses for its voice and video calls. It’s a library containing a lot of Rust code specific to Signal’s needs, see e.g. https://signal.org/blog/how-to-build-encrypted-group-calls/. It wraps WebRTC, the Chromium-library that’s used for voice and video calls in browsers. Specifically, it wraps a fork of WebRTC that contains additional security features, and some other Signal-specific changes.

Whisperfish is quite special in its use of RingRTC. In Signal Android, RingRTC can be loaded as a JNI library, separated from other C libraries. Whisperfish loads RingRTC as a Rust library, and it’s built as part of the Whisperfish build process. The WebRTC library, however, ships its own set of dependencies, by default statically linked into the library. This conflicts with our own shipping of OpenSSL 3 (as a dep for sqlcipher).

Building WebRTC without boringssl built-in is possible, but it’s not straightforward, especially since the necessary patches are not yet present in Signal’s fork of WebRTC. I have built WebRTC specifically for use in Whisperfish, and the resulting static libraries are available at https://nas.rubdos.be/~rsmet/webrtc/ . This post documents how I did that.

Cherry picks

Specifically this commit was needed to build WebRTC with BoringSSL as a dynamic system library:

  • 459d6b1d9b - build: add options to configure libsrtp for boringssl or other libraries (9 days ago) <Philipp Hancke> This required a bit of merging to get it in. I also toyed with versions of dependencies to get things to link, but in the end that didn’t seem to matter much. They are in the no-ssl branch of my fork of WebRTC: https://github.com/whisperfish/webrtc/tree/no-ssl

Downloading WebRTC

One would hope that building WebRTC is as simple as git clone and ninja build, but it’s not. Google has a whole repository of shady-looking git wrappers and scripts to build WebRTC. This is mostly because WebRTC is a huge project with a lot of dependencies. Find the instructions at https://webrtc.github.io/webrtc-org/native-code/development/. Crucially, you need to alter the .gclient file after checking out the repo, to point to either Signal’s fork or now my fork:

solutions = [
  {
    "name": "src",
    "url": "https://github.com/signalapp/webrtc",
    "deps_file": "DEPS",
    "managed": False,
    "custom_deps": {},
  },
]

or

solutions = [
  {
    "name": "src",
    "url": "https://github.com/whisperfish/webrtc",
    "deps_file": "DEPS",
    "managed": False,
    "custom_deps": {},
  },
]

I am currently not sure how to tell gclient to use the no-ssl branch. I created the no-ssl branch, and continued from there. I think you can manually check out the branch, and then run gclient sync to get the correct dependencies on top.

Building

In the end, the following script yields four libwebrtc.a files:

#!/bin/bash -ex

export PATH=${PWD}/depot_tools:$PATH

export WEBRTC_VERSION=6478k
export WEBRTC_REVISION="branch-heads/${WEBRTC_VERSION}"

pushd src

NO_SSL="rtc_build_ssl=false libsrtp_build_boringssl=false no_build_ssl=true"

for arch in arm arm64 x86 x64; do
    gn gen out/$arch --args="is_debug=false target_cpu=\"$arch\" rtc_build_examples=false rtc_build_tools=false rtc_use_x11=false rtc_enable_sctp=false rtc_libvpx_build_vp9=true rtc_include_ilbc=false rtc_disable_metrics=true rtc_disable_trace_events=true rtc_include_tests=false rtc_enable_protobuf=false symbol_level=1 $NO_SSL"

    ninja -C out/$arch
done

popd

Most of the build flags come from Signal’s build script, and I added the ssl-related flags.

The resulting files are hosted on my home server, and include a SHA384 hash that is used in the Whisperfish CI build to verify the download.

The compiler that is shipped used in the ninja cross-build system is rather recent, but luckily the new SailfishOS 4.6 SDK is recent enough to handle the artifacts. The 4.5 SDK is not recent enough.

Building against OpenSSL3

The above script builds WebRTC against the default OpenSSL 1.1.1 (since SailfishOS ships that). Since most modern Linux systems ship OpenSSL 3.x, we also need artifacts that are built against OpenSSL 3.x.

You can build this by downloading the OpenSSL 3.2.2 tarball, running ./configure, and then running the adapted script:

#!/bin/bash -ex

export PATH=${PWD}/depot_tools:$PATH

export WEBRTC_VERSION=6478k
export WEBRTC_REVISION="branch-heads/${WEBRTC_VERSION}"

SSL_INCLUDE="rtc_ssl_root=\"${PWD}/openssl-3.2.2/include\" libsrtp_ssl_root=\"${PWD}/openssl-3.2.2/include\""

pushd src

NO_SSL="rtc_build_ssl=false libsrtp_build_boringssl=false no_build_ssl=true"

for arch in arm arm64 x86 x64; do
    gn gen out/$arch --args="is_debug=false target_cpu=\"$arch\" rtc_build_examples=false rtc_build_tools=false rtc_use_x11=false rtc_enable_sctp=false rtc_libvpx_build_vp9=true rtc_include_ilbc=false rtc_disable_metrics=true rtc_disable_trace_events=true rtc_include_tests=false rtc_enable_protobuf=false symbol_level=1 $NO_SSL $SSL_INCLUDE"

    ninja -C out/$arch
done

popd

The includes seem to be architecture-independent enough, that we don’t need to ./configure them for each architecture.