Guide to upgrading NSS

Our components rely on cryptographic primitives provided by NSS. Every month or so, a new version of NSS is published and we should try to keep our version as up-to-date as possible.

Because it makes unit testing easier on Android, and helps startup performance on iOS, we compile NSS ourselves and link to it statically. Note that NSS is mainly used by Mozilla as a dynamic library and the NSS project is missing related CI jobs (iOS builds, windows cross-compile builds etc.) so you should expect breakage when updating the library (hence this guide).


Updating the Version

The build code is located in the libs/ folder.

The version string is located in the beginning of build-all.sh.

For most NSS upgrades, you'll need to bump the version number in this file and update the downloaded archive checksum. Then follow the steps for Updating the cross-compiled NSS Artifacts below. The actual build invocations are located in platform-specific script files (e.g. build-nss-ios.sh) but usually don't require any changes.

To test out updating NSS version:

  • Ensure you've bumped the NSS in build-all.sh
  • Clear any old NSS build artifacts: rm -rf ./libs/desktop && cargo clean
  • Install the updates version: ./libs/verify-desktop-environment.sh
  • Try it out: cargo test

Updating the Cross-Compiled NSS Artifacts

We use a Linux TC worker for cross-compiling NSS for iOS, Android and Linux desktop machines. However, due to the complexity of the NSS build process, there is no easy way for cross-compiling MacOS and Windows -- so we currently use pre-built artifacts for MacOS desktop machines (ref #5210).

  1. Look for the tagged version from the NSS CI

    usually a description with something like Added tag NSS_3_90_RTM

  2. Select the build for the following system(s) (first task with the title "B"):
    • For Intel MacOS: mac opt-static
  3. Update taskcluster/ci/fetch/kind.yml, specifically nss-artifact task to the appropriate url and checksum and size

    Note: To get the checksum, you can run shasum -a 256 {path-to-artifact} or you can make a PR and see the output of the failed log.

  4. Update the SHA256 value for darwin cross-compile in libs/build-nss-desktop.sh to the same checksum as above.
  5. Once the pull request lands, build-nss-desktop.sh should be updated once more using the L3 cache Taskcluster artifact.

Exposing new functions

If the new version of NSS comes with new functions that you want to expose, you will need to:

  • Add low-level bindings for those functions in the nss_sys crate; follow the instructions in README for that crate.
  • Expose a safe wrapper API for the functions from the nss crate;
  • Expose a convenient high-level API for the functions from the rc_crypto crate;

Tips for Fixing Bustage

On top of the primitives provided by NSS, we have built a safe Rust wrapper named rc_crypto that links to NSS and makes these cryptographic primitives available to our components.

The linkage is done by the nss_build_common crate. Note that it supports a is_gecko feature to link to NSS dynamically on Desktop.

Because the NSS static build process does not output a single .a file (it would be great if it did), this file must describe for each architecture which modules should we link against. It is mostly a duplication of logic from the NSS gyp build files. Note that this logic is also duplicated in our NSS lib build steps (e.g. build-nss-desktop.sh).

One of the most common build failures we get when upgrading NSS comes from NSS adding new vectorized/asm versions of a crypto algorithm for a specific architecture in order to improve performance. This new optimized code gets implemented as a new gyp target/module that is emitted only for the supported architectures. When we upgrade our copy of NSS we notice the linking step failing on CI jobs because of undefined symbols.

This PR shows how we update nss_common_build and the build scripts to accommodate for these new modules. Checking the changelog for any suspect commit relating to hardware acceleration is rumored to help.