Skip to content
Hubert Kario edited this page Mar 22, 2024 · 53 revisions

In the README.md there is a description how to run the different servers when they are already installed in the system. This doesn't work in case of testing new features like TLS 1.3.

This document will explain how to compile and configure different servers using current development versions of packages.

TODO: figure out what dependencies do the different projects require

TODO: handling of older, supported, branches of OpenSSL and GnuTLS

TODO: building the servers with clang with asan and ubsan enabled

Table of Contents

  1. Complete testing
  2. Keys and Certificates
  3. OpenSSL
  4. GnuTLS
  5. NSS
  6. tlslite-ng
  7. Go crypto/tls package
  8. Java

Complete testing

The configurations listed below set up the servers with just one or two certificates and fairly simple configurations. From experience, working with different versions of those implementations, to provide complete coverage of the implementations, the following settings are known to have impact on server behaviour (e.g. there were bugs which manifested themselves with use of SNI virtual host, but not against a 'default' host):

  1. one vs many certificates set up (especially relevant for certificates with rsaEncryption vs rsassa-pss Subject Public Key Info)
  2. no SNI configured vs SNI configured
  3. testing of a default host vs SNI host of a SNI-enabled server
  4. different security levels (e.g. OpenSSL with cipherstring @SECLEVEL=3 vs @SECLEVEL=0 or GnuTLS NORMAL vs SECURE256:%PROFILE_HIGH)
  5. no client certificates, requesting client certificates, mandating client certificates
  6. ALPN (NPN) vs no ALPN configured
  7. session tickets enabled vs disabled (session ID behaviour in TLS 1.2)
    1. what kind of session tickets are used in TLS 1.3 (e.g. OpenSSL will use session-id-like tickets in TLS 1.3 if session tickets are disabled in TLS 1.2)
  8. support for TLS 1.3 0-RTT enabled vs disabled (e.g. even with 0-RTT disabled, the server needs to still be able to process 0-RTT Client Hello)
  9. supported versions enabled (e.g. when server that implements TLS 1.2 but enables TLS 1.1 as the highest one receives FALLBACK_SCSV in TLS 1.1 ClientHello, it MUST NOT abort the connection)
  10. changes to configuration before session is established and resumed (e.g. resuming a session with a cipher that is now disabled or processing 0-RTT data with cipher that is now disabled)
  11. integrated with different applications (as callbacks may cause the behaviour to be very different than vanilla library, or the application may use the API incorrectly – CVE-2019-1559)
  12. Large client and/or server certificates (e.g. https://10000-sans.badssl.com/ )
  13. key stored on an HSM or smartcard (as card may not support all signature methods or hashes)
    • smartcard with different features supported – rsa-pss supported natively vs not, SHA-384 supported vs not, etc
  14. specific extension or feature of protocol being disabled, enabled and mandated (e.g. difference in behaviour when safe renegotiation is enabled vs. when it is required for connection, or when PHA is enabled, specific curves signature algorithms or ciphers disabled)
  15. server running under valgrind, compiled with asan, ubsan, etc. Verification that it doesn't suffer from unbounded memory growth (accounted for, but not promptly freed memory)
  16. force-enabled features that are deprecated in later protocol versions (e.g. PKCS#1 SHA-1 signatures enabled through config option while negotiating TLS 1.3 or secp256k1 curve enabled and TLS 1.3 negotiated)
  17. server running on different hardware (e.g. one that has assembly implementation of a "stitched" cipher vs one that doesn't, AES-NI vs no hardware acceleration, SSE3 vs no SSE3, etc.)
  18. interaction between server implementation versions with session resumption – what happens if a session started with previous version of library is resumed with a new one or vice versa (requires both versions to use the same ticket encryption key)

Keys and Certificates

The servers require keys and certificates to function, following commands can be used to generate them and prepare for use with different libraries:

  1. Download and import bash library:
    pushd /tmp &&
    wget https://raw.githubusercontent.com/redhat-qe-security/certgen/master/certgen/lib.sh &&
    source lib.sh
    
  2. Generate keys:
    x509KeyGen ca &&
    x509KeyGen server &&
    x509KeyGen client &&
    x509KeyGen -t ecdsa -s prime256v1 server-p256 &&
    x509KeyGen -t ecdsa -s prime256v1 client-p256
    
  3. Sign certificates:
    x509SelfSign ca &&
    x509CertSign --CA ca server &&
    x509CertSign --CA ca --DN "O=P-256 server" --DN 'CN=localhost' server-p256 &&
    x509CertSign --CA ca -t webclient client &&
    x509CertSign --CA ca -t webclient --DN "CN=P-256 Client" client-p256
    
  4. Export key and certificate to PKCS#12 files:
    x509Key --pkcs12 --with-cert server &&
    x509Key --pkcs12 --with-cert server-p256
    
  5. Generate NSS database and import keys and certificates to it
    mkdir /tmp/nssdb &&
    certutil -N -d sql:/tmp/nssdb --empty-password &&
    certutil -A -d sql:/tmp/nssdb -n ca -i /tmp/ca/cert.pem -t 'cTC,cTC,' -a &&
    pk12util -i /tmp/server/bundle.p12 -d sql:/tmp/nssdb -W '' &&
    pk12util -i /tmp/server-p256/bundle.p12 -d sql:/tmp/nssdb -W ''
    
  6. Return to previous directory
    popd
    

OpenSSL

  1. Download the code:
    git clone https://github.com/openssl/openssl.git
    
  2. Configure it so that it is easy to run (statically built)
    cd openssl
    ./config no-shared
    
  3. Compile
    make -j4
    

Start OpenSSL server

Regular configuration

apps/openssl s_server -www -key /tmp/server/key.pem -cert \
/tmp/server/cert.pem -dkey /tmp/server-p256/key.pem -dcert \
/tmp/server-p256/cert.pem

With client certificates

apps/openssl s_server -www -key /tmp/server/key.pem -cert \
/tmp/server/cert.pem -verify 1 -CAfile /tmp/ca/cert.pem \
-dkey /tmp/server-p256/key.pem -dcert /tmp/server-p256/cert.pem

Updating

To update the repository, after the master branch moved, execute the following command in the openssl directory:

git pull origin master

Then you can compile it again, as in the steps above:

make clean
./config no-shared
make -j4

GnuTLS

  1. Install dependencies (command for Fedora RHEL, for other distributions see the helpful info in gnutls README.md)
    dnf -y install dash git autoconf libtool gettext-devel automake autogen \
    nettle-devel p11-kit-devel autogen-libopts-devel libunistring-devel \
    trousers-devel guile-devel libtasn1-devel libidn2-devel gawk gperf \
    libtasn1-tools unbound-devel bison help2man gtk-doc texinfo texlive \
    libev-devel patch wget
    
    (texlive is probably an overkill)
  2. Download the code:
    git clone https://gitlab.com/gnutls/gnutls.git
    
  3. Configure so that it is easy to run:
    cd gnutls
    ./bootstrap
    ./configure --disable-doc
    
  4. Compile:
    make -j$(nproc)
    

Start GnuTLS server

To start the GnuTLS server, use the following commands:

cd doc/credentials
./gnutls-http-serv \
--priority NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+DHE-PSK:+PSK \
-p 4433 -a -d 6

note: the configured PSKs are in the psk-passwd.txt file

Updating

Similarly to OpenSSL, local code can be updated by running the following commands:

git pull origin master

Then to recompile use the following commands:

./configure --disable-doc
make -j$(nproc)

NSS

NSS is the Mozilla TLS implementation used by Firefox.

  1. Download the code:
    mkdir nss-devel
    hg clone https://hg.mozilla.org/projects/nspr
    hg clone https://hg.mozilla.org/projects/nss
    
    (Because nss compilation creates a directory on the same level as nss and nspr directories live, I suggest to keep it contained inside the nss-devel dir)
  2. Compile:
    cd nss
    USE_64=1 make nss_build_all
    

Run NSS server

To run the server you need to find the directory containing the newest compile:

cd ..
NSS_DIR="$(pwd)/dist/$(cat dist/latest)"

Note: that this needs to be done every time the optimisation options of the compile, the compiler, or the system's kernel changes.

Start the server:

LD_LIBRARY_PATH="$NSS_DIR/lib" "$NSS_DIR/bin/selfserv" -d \
sql:/tmp/nssdb -p 4433 -V tls1.0: -H 1 -n server \
-e server-p256 -u

Or one that asks for client certificates:

LD_LIBRARY_PATH="$NSS_DIR/lib" "$NSS_DIR/bin/selfserv" -d \
sql:/tmp/nssdb -p 4433 -V tls1.0: -H 1 -n server \
-e server-p256 -u -r

Updating

The process to update the NSS repository is a bit different as it lives in two different directories and uses mercurial instead of git:

cd nspr
hg pull
hg up default
cd ../nss
hg pull
hg up default
cd ..

Recompilation is as easy as for other projects though:

cd nss
USE_64=1 make nss_clean_all
USE_64=1 make nss_build_all
cd ../
NSS_DIR="$(pwd)/dist/$(cat dist/latest)"

tlslite-ng

Note, it depends on python ecdsa module, see its README.md file for details.

  1. Download:
    git clone https://github.com/tomato42/tlslite-ng.git
    

Running the tlslite-ng server

cd tlslite-ng
PYTHONPATH=. python scripts/tls.py server \
-c tests/serverX509Cert.pem -k tests/serverX509Key.pem \
-c tests/serverECCert.pem -k tests/serverECKey.pem \
localhost:4433

Or one that asks for client certificates:

PYTHONPATH=. python scripts/tls.py server \
-c tests/serverX509Cert.pem -k tests/serverX509Key.pem \
-c tests/serverECCert.pem -k tests/serverECKey.pem \
--reqcert localhost:4433

Updating

To update, only downloading new code is necessary:

git pull origin master

Go crypto/tls package

  1. Install server program:
    unset GOPATH
    go install github.com/ueno/go-tlsdriver/cmd/server@latest
    

Running the server

$HOME/go/bin/server --http \
--certfile tests/serverX509Cert.pem --keyfile tests/serverX509Key.pem \
--certfile tests/serverECCert.pem --keyfile tests/serverECKey.pem \
--address localhost:4433

Or one that asks for client certificates:

$HOME/go/bin/server --http \
--certfile tests/serverX509Cert.pem --keyfile tests/serverX509Key.pem \
--certfile tests/serverECCert.pem --keyfile tests/serverECKey.pem \
--client-auth RequestClientCert \
--address localhost:4433

Updating

To update, only downloading new code is necessary:

go install github.com/ueno/go-tlsdriver/cmd/server@latest

Java

Like Go, Java doesn't ship with a command line utility to start a HTTPS server. The code that can be used to do that is in the 3rd-party-scripts directory.

  1. Install the Java Development Kit (the javac command needs to be available)
  2. Convert the key into a Java Key Store (jks) file:
    openssl pkcs12 -export -in tests/serverX509Cert.pem -inkey tests/serverX509Key.pem -out key.p12 -name localhost -passout pass:
    keytool -importkeystore -destkeystore testkey.jks -srckeystore key.p12 -srcstoretype PKCS12 -srcstorepass '' -deststorepass password
    
  3. Compile the SimpleHTTPSServer.java:
    javac SimpleHTTPSServer.java
    
  4. Make sure the testkey.jks is in the same directory as the SimpleHTTPSServer.java and start the server:
    java -cp . SimpleHTTPSServer