Modifying Mochitest SSL behavior

Mochitest provides functionality for tests to effectively simulate execution across a wide variety of protocols, hosts, and ports, including over SSL using the https protocol.  The vast majority of tests can use existing functionality, but occasionally a test may need new functionality to be written, particularly if it uses SSL in non-trivial ways.  This article documents how SSL in Mochitest is implemented and how you can modify its behavior to add support for particular needs.

SSL certificate management

For default SSL Mochitest capability there is a pair of a persistent testing certification authority certificate and an on-demand generated server certificate. This schema provides simulation of a common model of a trusted certificate issuer and a trusted server in the Internet.

The certification authority (CA) certificate is a pre-generated self-signed certificate, valid for 10 years. This CA certificate resides in build/pgo/certs/pgoca.p12 (PKCS12 module) and build/pgo/certs/ (the issuer certificate itself) and both files are permanently stored to the repository. The CA certificate is at run-time added as trusted to the certificate database of the testing profile what ensures no need to manually add an exception when you wish to use the common list of https hosts.

The default server certificate resides in the certificate database stored permanently to the repository, in the build/pgo/certs/ directory of the source tree. The certificate is based on the list in build/pgo/server-locations.txt and is signed by the certification authority certificate described above. Each https host is added to the server certificate's subject as an alternative domain name (SubjectAltName) to make the host accessible.

In general, any file in build/pgo/certs/ with the extension .ca is considered a certification authority certificate in ASCII BASE64 format and is added as trusted to the testing profile. The default CA is such a file.

Customizing the list of https hosts

To simply add a new https host for which the default server certificate will be used just add it to the list in server-locations.txt. The content is self explanatory. To reflect these changes run:

# Linux/Mac
$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/ --gen-server
# Windows
$objdir/_virtualenv/Scripts/python.exe $topsrcdir/build/pgo/ --gen-server

To add a new https host that has no server certificate assigned, even the default one, just add an option 'nocert' after the host name, like this:

# This is a host without any certificate         privileged,nocert
This host is already present in the list of hosts.

Creating a new host with a new certificate

To add a new host with a new server certificate, different from the default one, you have to generate or provide the certificate and bound it with the host. Just decide if you want to sign it by the prepared CA certificate or create a new CA certificate by your self to sign the new server certificate or create a self-signed server certificate or add your own certificate and key you already have.

Note: to generate new certificates it is most appropriate to use certutil and pk12util binaries built as part of a test-enabled build. These utils reside in obj-dir/dist/bin.

Note: you will change the certificate database while creating a new certificate. Thus, don't forget to commit the new certificate database with the new test.


I. Use the prepared CA to create a new server certificate.

Note: in this case keep the command to generate your server certificate for case when the prepared CA get renewed. You must then generate the server certificate again.

To generate your new certificate: (please replace "My" names with something meaningful)

    build/pgo/certs$ certutil -S -n "MyNewTestingServerCert" -s "" -c "pgo temporary ca" -t "P,," -k rsa -g 1024 -m <LARGE RANDOM NUMBER> -v 120 -d .

      follow on-screen instructions, "pgo temporary ca" is nickname of the prepared CA present in the database
      IMPORTANT NOTE: make sure you allocate a new unique serial number (the '-m' option). If there were two or more certificates with the same
serial number signed by the pgo CA the ssltunnel server would not start! It is best to assign a large random number.

II. Create my own CA and server certificate:

1. create a new CA certificate: (please replace "My" names with something meaningful)

      build/pgo/certs$ certutil -S -s "MyNewCertificationAuthority" -s "CN=My Certificate Authority" -t "C,," -x -m 1 -v 120 -n "my certificate authority" -2 -d .
      type 'Y', confirm with enter
      type '0' (zero), confirm with enter
      type 'N', confirm with enter

2. generate the server certificate as described in previous section, just make sure to change the '-c "pgo temporary ca"' to '-c "my certificate authority"' to reflect you want to sign the server certificate by your new CA certificate

3. export the CA certificate:

    build/pgo/certs$ certutil -L -d . -n "my certificate authority" -a -o
      add this file to the repository, it must be checked in with the new test

      optionally, if you wish to save the CA cert with its private key, do:
    build/pgo/certs$ pk12util -o myca.p12 -n "my certificate authority" -d .
      provide any password you wish

      to delete your CA certificate from the database (recommended), do:
    build/pgo/certs$ certutil -D -n "my certificate authority" -d .

III. Create self signed server certificate:

to generate a self signed server certificate: (please replace "My" names with something meaningful)

    build/pgo/certs$ certutil -S -n "MySelfSignedServerCertificate" -s "" -x -t "P,," -m 1 -v 120 -d .

IV. Add my own certificate and private key I already have

1. import the existing server certificate and its private key from PKCS12 module:

    build/pgo/certs$ pk12util -i my-own-server-cert.p12 -d .
      enter correct password of the PKCS12 module, nickname of the cert will be used to refer it in server-locations.txt, see bellow

2. optionally, if there is also a CA certificate the server certificate is signed with and you need that CA be trusted, copy this CA to build/pgo/certs and give it a '.ca' extension, the file should be an X.509 certificate in ASCII BASE64 formatting, make sure to commit this file as well

Now you must let Mochitest know about your new server certificate. Edit the server-locations.txt as follows:
    # My testing host and its bond to certificate nickname in the certificate database   privileged,cert=MyNewTestingServerCert

Run make at obj-dir/testing/mochitest to reflect the changes. If the build fails it is possible you created a certificate with a same serial number as another certificate signed by the same certification authority or two server certificates has a same nickname.

Regenerating the temporary CA certificate

The testing CA is valid for 10 years, so this shouldn't be a problem very often, but occasionally it may be necessary to generate a new testing CA.  To do so, use script like this:

obj-dir/_profile/pgo$ --gen-ca

This will re-create a CA with a different public and private key pair valid from that moment for next 10 years. You must make $objdir/testing/mochitest after this operation to reflect the changes. Don't forget to commit changed and pgoca.p12 files to the repository. Because the CA's public key changes during this operation keep a command generating your server certificates based on this CA to regenerate them easily. Signatures of your server certificates will become invalid after re-generation of the CA.