Software verification is a critical step in the use of secure applications but it has traditionally been hard to provide, especially from a user perspective. Usual solutions are:

  • Using HTTPS to download. But in the case of Tails, we are serving so many downloads that we have to rely on mirrors hosted by third parties. HTTPS also doesn't protect from interrupted downloads leading to broken Tails installations.
  • Providing OpenPGP signatures. But this really works only for the few people who know how to verify an OpenPGP signature and use the OpenPGP Web-of-Trust correctly.

We are trying here to provide a usable solution to verify a download done through HTTP, while relying on cryptographic information fetched elsewhere through HTTPS (and possibly with stronger authentication mechanisms such as public key pinning from browser vendors).

We use for that a browser extension, called Tails Verification which is available for

  • Firefox 52+ (and Tor Browser 7+)
  • Chrome 57+

i.e. browsers that support WebAPIs, in particular FileReader, Fetch, and async/await.

The code of Tails Verification is available in git clone https://git-tails.immerda.ch/verification-extension.

Related documents

Scope

Goals

Provide a simple, automated, and cross-platform technique to verify installable Tails images of the current version, in ISO and disk image format.

Non goals

  • Verify deprecated Tails images.
  • Verify Tails images downloaded from nightly.tails.boum.org.
  • Verify Tails images downloaded through BitTorrent. If we can rely on our website to provide a correct cryptographic description of the Tails image then we can rely on it as well to provide a correct BitTorrent file. Then we rely on the BitTorrent client to verify the integrity of the download (#9043).

However, any current Tails image (downloaded over BitTorrent, copied from a friend, downloaded from one of our mirrors) can be verified by the extension.

Security considerations

Threat model

We are considering here an attacker who can:

  • [A] Provide a malicious Tails image to the user for example by operating a rogue Tails mirror.

  • [H] Operate a website that is loaded in a different tab in the same browser as the extension. See the section on security inside the browser.

We are not considering an attacker who can:

  • [B] Do a man-in-the-middle attack by providing a rogue HTTPS certificate for https://tails.boum.org/ signed by a certificate authority trusted by the browser but under the control of the attacker.

    Since the extension is targeted at new users, a MitM or exploit on our website could defeat any verification technique by providing simplified instructions or by faking Tails image verification.

    Note that our website is already in the HSTS preload list of Firefox and Chrome which forces HTTPS connections to our website, even for first time visitors.

  • [C] Insert malicious content on https://tails.boum.org/ through an exploit on our website as this could trick new users to skip the Tails image verification all the way. To prevent this kind of attack we should instead:

    • Monitor externally the most relevant parts of our website.
    • Work on integrating full upgrades in Tails Upgrader to limit the number of times people have to rely on our website to upgrade. See #7499.
  • [D] Insert malicious information in our main Git repository as such an attacker could do attack [C] as well.

  • [E] Insert targeted malware on the user's computer as this could defeat any possible verification mechanism that such an extension could do.

  • [F] Provide a rogue extension to the user as this could defeat any possible verification mechanism that such an extension could do.

  • [G] Insert malicious content on https://tails.boum.org/ after taking control of the web server, or entire system, behind it. Such an attacker could do attack [C] as well but in such a way that could be much harder to detect (for example by serving malicious content only to some users).

    To mitigate such an attack in some cases we could both:

    • Encourage external documentation (screencasts on YouTube, printed forms, etc.). But those would be vulnerable to other kind of attacks.
    • Not rely on the website to perform the Tails image verification and rely on a native interface accessible from the add-ons menu.

    But the cost/benefit of such a technique is not very appealing…

  • [I] Provide a malicious extension in the same browser as this would have similar effects to attack [F].

  • [J] Provide a malicious copy of our website on a similar looking URL that could pretend that verification has succeeded without actually verifying anything.

Security inside the browser

The threat described as [H] is taken care of by the internals of the browser (and the proper coding of the extension).

Cross-origin communication

The extension uses cross-origin communication to send messages to the download page.

  • To ensure that messages from the extension are only sent to pages on our website, the extension sets targetOrigin to https://tails.boum.org (no trailing slash needed) in postMessage. See commit c87ce92.

  • Before processing the message, the download page verifies that it is coming from:

    • The same tab (event.source is window)
    • Our website (event.origin is https://tails.boum.org, no trailing slash needed)

    See receiveMessage() in download.js.

  • The code of the extension is loaded via content scripts and targets only tabs with locations https://tails.boum.org/install/* and https://tails.boum.org/upgrade/*. See permissions in manifest.json.

  • On Chrome browsers, a background script reloads tabs with matching URL schemes (https://tails.boum.org/install/* and https://tails.boum.org/upgrade/*) only after the first installation of the extension, in order to make the extension usable right away. This is automatically happening in Firefox based browsers, therefore the background script does not apply.

  • The communication is unidirectional: the extension only sends messages but it does not listen to messages.

Content Security Policy

The extension uses a Content Security Policy with default-src 'none' and script-src 'self'. The latter part has been added because background scripts are needed by the extension, and require a slightly less strict CSP. However, this CSP also applies to the content scripts shipped in the extension.

Update mechanisms

Automatic update from browsers

Enforce version check on our download page

On top of this, the HTML code of our download page includes a tag to force a minimum version of the extension. For example:

<div id="extension-version">2.0</div>

Tails Verification checks the value of this tag and asks for an update if its version is lower than the requested version number.

This mechanism might be useful to force updated extensions with a finer time granularity that the native automatic updates from the browsers.

Functioning

Extension technology

The extension is written as a Web Extension and the same exact code works on both Firefox and Chrome.

Future plans include abandoning the extension and integrating the code directly into our website, with the aim of supporting more browsers. #16128.

Data source

Building upon the format specified for upgrade description files, the verification extension fetches an image description file from our server to retrieve all the information it needs about available Tails images (URL, size, checksum, etc.).

The file format allows to publish several target files, and formats, such as ISO and IMG.

It currently publishes only information about the current stable supported Tails release. A more fine grained approach is planned #16200.

Currently, this image description file is not signed using OpenPGP.

Example of an image description file

{
    "build_target": "amd64",
    "channel": "stable",
    "installations": [
        {
            "installation-paths": [
                {
                    "target-files": [
                        {
                            "sha256": "2ffeacab6ad74671a9eb15b560f47bae7d22e1bcbd9735342ee6d7dfe3c5706e",
                            "size": 1225568256,
                            "url": "http://dl.amnesia.boum.org/tails/stable/tails-amd64-3.11/tails-amd64-3.11.iso"
                        }
                    ],
                    "type": "iso"
                },
                {
                    "target-files": [
                        {
                            "sha256": "cafedeadbeaf67213970783432cafe0dead9beefbd9735342ee6d7dfe3c5706e",
                            "size": 1225765432,
                            "url": "http://dl.amnesia.boum.org/tails/stable/tails-amd64-3.11/tails-amd64-3.11.img"
                        }
                    ],
                    "type": "img"
                }
            ],
            "version": "3.11"
        }
    ],
    "product-name": "Tails"
}

Checksum verification

When verifying a Tails image, the extension:

Security properties:

  • This technique would defeat attack [A] (malicious Tails image).

More complex verification mechanisms could be gradually built in to defeat attacks [B], [C], [D], [F], and [G].

Embedded Forge library

Contrary to its predecessor (DAVE), Tails Verification cannot rely on native API calls to calculate the checksum. So it embeds the Forge library:

https://github.com/digitalbazaar/forge/

We chose Forge because it was reported as being the fastest in this benchmark:

https://github.com/brillout/test-javascript-hash-implementations

Manipulation of the download page

The extension modifies what is displayed on the page using two different mechanisms:

  • Mostly through message communication (postMessage) sent to a script on the page (wiki/src/install/inc/js/download.js).

  • If an extension is already installed when the page is loaded, through an HTML attribute (documentElement.dataset.extension) corresponding to some CSS declarations, to indicate whether the extension is up-to-date or outdated.

This decouples the code of the extension from the implementation of the display on the HTML page (ids, classes, etc.).

When JavaScript is disabled, the page instructs the user to temporarily allow JavaScript on the page (through NoScript, the most likely scenario):

They can otherwise still download using BitTorrent.