diff --git a/.travis.yml b/.travis.yml index 5e14d66..3877f5a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: required -dist: trusty +dist: bionic language: c before_install: @@ -9,8 +9,6 @@ before_install: script: - make sslscan CC=clang - make sslscan CC=gcc - # OpenSSL can't be compiled out-of-the box with clang, see - # http://wiki.openssl.org/index.php/Compilation_and_Installation#Modifying_Build_Settings - #- make static CC=clang + - make static CC=clang - make static CC=gcc - make -f Makefile.mingw diff --git a/Changelog b/Changelog index bc94b58..051cfef 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,18 @@ Changelog ========= +Version: 2.0.0-alpha1 +Date : 22/02/2020 +Author : rbsec +Changes: The following are a list of changes + > Major rewrite of backend scanning code. + > Support for additional cipher suites. + > Support for TLSv1.3 + > Support for SSLv2 and SSLv3 protocol detection regardless of + OpenSSL. + > Checks for server key exchange groups. + > Checks for server signature algorithms. + Version: 1.11.13 Date : 24/03/2019 Author : rbsec diff --git a/Makefile b/Makefile index 11c51ff..d3e6462 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ BINDIR = $(PREFIX)/bin MANDIR = $(PREFIX)/share/man MAN1DIR = $(MANDIR)/man1 -WARNINGS = -Wall -Wformat=2 -Wformat-security +WARNINGS = -Wall -Wformat=2 -Wformat-security -Wno-deprecated-declarations DEFINES = -DVERSION=\"$(GIT_VERSION)\" # for dynamic linking @@ -49,10 +49,7 @@ CFLAGS += -D_FORTIFY_SOURCE=2 -fstack-protector-all -fPIE # Don't enable some hardening flags on OS X because it uses an old version of Clang ifneq ($(OS), Darwin) ifneq ($(OS), SunOS) -# Cygwin's linker does not support -z option. -ifneq ($(findstring CYGWIN,$(OS)),CYGWIN) - LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -endif + LDFLAGS += -pie -z relro -z now endif endif @@ -61,7 +58,7 @@ ifeq ($(STATIC_BUILD), TRUE) PWD = $(shell pwd)/openssl LDFLAGS += -L${PWD}/ CFLAGS += -I${PWD}/include/ -I${PWD}/ -LIBS = -lssl -lcrypto -lz +LIBS = -lssl -lcrypto -lz -lpthread ifneq ($(OS), FreeBSD) LIBS += -ldl endif @@ -75,6 +72,14 @@ LDFLAGS += -L/usr/local/lib -L/usr/local/ssl/lib -L/usr/local/opt/openssl/lib CFLAGS += -I/usr/local/include -I/usr/local/ssl/include -I/usr/local/ssl/include/openssl -I/usr/local/opt/openssl/include -I/opt/local/include -I/opt/local/include/openssl endif +# Find the number of processors on the system (used in -j option in building OpenSSL). +# Uses /usr/bin/nproc if available, otherwise defaults to 1. +NUM_PROCS = 1 +ifneq (,$(wildcard /usr/bin/nproc)) + NUM_PROCS = `/usr/bin/nproc --all` +endif + + .PHONY: all sslscan clean install uninstall static opensslpull all: sslscan @@ -114,28 +119,31 @@ uninstall: true opensslpull: if [ -d openssl -a -d openssl/.git ]; then \ - cd ./openssl && git checkout OpenSSL_1_0_2-stable && git pull | grep -q "Already up-to-date." && [ -e ../.openssl.is.fresh ] || touch ../.openssl.is.fresh ; \ + cd ./openssl && git checkout OpenSSL_1_1_1-stable && git pull | grep -q "Already up-to-date." && [ -e ../.openssl.is.fresh ] || touch ../.openssl.is.fresh ; \ else \ - git clone --depth 1 -b OpenSSL_1_0_2-stable https://github.com/PeterMosmans/openssl ./openssl && cd ./openssl && touch ../.openssl.is.fresh ; \ + git clone --depth 1 -b OpenSSL_1_1_1-stable https://github.com/openssl/openssl ./openssl && cd ./openssl && touch ../.openssl.is.fresh ; \ fi # Need to build OpenSSL differently on OSX ifeq ($(OS), Darwin) openssl/Makefile: .openssl.is.fresh - cd ./openssl; ./Configure -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC enable-ssl2 enable-weak-ssl-ciphers zlib darwin64-x86_64-cc + cd ./openssl; ./Configure -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC enable-weak-ssl-ciphers zlib darwin64-x86_64-cc # Any other *NIX platform else openssl/Makefile: .openssl.is.fresh - cd ./openssl; ./config -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC no-shares enable-weak-ssl-ciphers enable-ssl2 zlib + cd ./openssl; ./config -v -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC no-shared enable-weak-ssl-ciphers zlib endif openssl/libcrypto.a: openssl/Makefile - $(MAKE) -C openssl depend - $(MAKE) -C openssl all - $(MAKE) -C openssl test + $(MAKE) -j $(NUM_PROCS) -C openssl depend + $(MAKE) -j $(NUM_PROCS) -C openssl all +# $(MAKE) -j $(NUM_PROCS) -C openssl test # Disabled because this takes 45+ minutes for OpenSSL v1.1.1. static: openssl/libcrypto.a - $(MAKE) sslscan STATIC_BUILD=TRUE + $(MAKE) -j $(NUM_PROCS) sslscan STATIC_BUILD=TRUE + +test: static + ./docker_test.sh clean: if [ -d openssl ]; then ( rm -rf openssl ); fi; diff --git a/Makefile.mingw b/Makefile.mingw index 70d4c5f..8357893 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -49,8 +49,8 @@ SECURITY_OPTIONS=-fstack-protector-all -D_FORTIFY_SOURCE=2 -Wformat -Wformat-sec # Turn on linker optimizations, and DEP support (--nxcompat) LINK_OPTIONS=-Wl,-O1 -Wl,--discard-all -Wl,--no-undefined -Wl,--dynamicbase -Wl,--nxcompat -static -CFLAGS += -Iopenssl_mingw/include -D__USE_GNU -LDFLAGS += -lws2_32 -lgdi32 +CFLAGS += -Iopenssl_mingw/include -D__USE_GNU -DOPENSSL_NO_SSL2 -Wno-deprecated-declarations +LDFLAGS += -lws2_32 -lgdi32 -lcrypt32 # Set the version string for the program. VERSION = "$(shell grep -E -o -m 1 "[0-9]+\.[0-9]+\.[0-9]+" Changelog) Windows $(ARCHITECTURE) (Mingw)" @@ -71,9 +71,9 @@ zlibpull: opensslpull: if [ -d openssl_mingw -a -d openssl_mingw/.git ]; then \ - cd ./openssl_mingw && git checkout OpenSSL_1_0_2-stable && git pull | grep -q "Already up-to-date." && [ -e ../.openssl_mingw.is.fresh ] || touch ../.openssl_mingw.is.fresh ; \ + cd ./openssl_mingw && git checkout OpenSSL_1_1_1-stable && git pull | grep -q "Already up-to-date." && [ -e ../.openssl_mingw.is.fresh ] || touch ../.openssl_mingw.is.fresh ; \ else \ - git clone --depth 1 -b OpenSSL_1_0_2-stable https://github.com/PeterMosmans/openssl ./openssl_mingw && cd ./openssl_mingw && touch ../.openssl_mingw.is.fresh ; \ + git clone --depth 1 -b OpenSSL_1_1_1-stable https://github.com/openssl/openssl ./openssl_mingw && cd ./openssl_mingw && touch ../.openssl_mingw.is.fresh ; \ fi zlib_mingw/libz.a: zlibpull diff --git a/README.md b/README.md index 8c80845..9885f8e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,25 @@ +# sslscan2 + +An alpha build of sslscan 2 has been merged into master. If you want the old code, +the tag [1.11.11-rbsec](https://github.com/rbsec/sslscan/tree/1.11.11-rbsec) was the last release in that branch. + +The main changes in sslscan2 is a major rewrite of the backend scanning code, +which means that it is no longer reliant on the version of OpenSSL for many checks. +This means that it is possible to support legacy protocols (SSLv2 and SSLv3), as well +as supporting TLSv1.3 - regardless of the version of OpenSSL that it has been compiled against. + +This has been made possible largely by the work of [jtesta](https://github.com/jtesta), who has been +responsible for most of the backend rewrite. + +Other key changes include: + +* Enumeration of server key exchange groups. +* Enumeration of server signature algorithms. +* SSLv2 and SSLv3 protocol support it scanned, but individual ciphers are not. +* A test suite is included using Docker, to verify that sslscan is functionality correctly. + +There are likely to be bugs in this version, so please report any that you encounter. + # README [![Build Status](https://travis-ci.org/rbsec/sslscan.svg?branch=master)](https://travis-ci.org/rbsec/sslscan) diff --git a/docker_test.sh b/docker_test.sh new file mode 100755 index 0000000..80c3cd3 --- /dev/null +++ b/docker_test.sh @@ -0,0 +1,569 @@ +#!/bin/bash + +# +# Copyright (C) 2019-2020 Joe Testa +# +# This script (adapted from the ssh-audit project) will set up a docker image with +# multiple SSL/TLS servers. They are each executed one at a time, and sslscan is run +# against them. The output of sslscan is compared against the expected output. If +# they match, the test passes; otherwise the test fails. +# +# +# For debugging purposes, here is a cheat sheet for manually running the docker image: +# +# docker run -p 4443:443 --security-opt seccomp:unconfined -it sslscan-test:3 /bin/bash +# + +# +# Running this script with no arguments causes it to build the docker image (if it +# doesn't yet exist), then run all tests. +# +# Running the script with a test number argument (i.e.: './docker_test.sh 2') will +# run the docker image for test #2 only (in the background) and do nothing else. This +# allows the test itself to be debugged. +# + + +# This is the docker tag for the image. If this tag doesn't exist, then we assume the +# image is out of date, and generate a new one with this tag. +IMAGE_VERSION=3 + +# This is the name of our docker image. +IMAGE_NAME=sslscan-test + + +# Terminal colors. +CLR="\033[0m" +RED="\033[0;31m" +GREEN="\033[0;32m" +REDB="\033[1;31m" # Red + bold +YELLOWB="\033[1;33m" # Yellow + bold +GREENB="\033[1;32m" # Green + bold + +# Set to 0 if any test fails. +all_passed=1 + + +# Number of processors on this system (used to compile parallel builds). +NUM_PROCS=`/usr/bin/nproc --all 2> /dev/null` +if [[ $NUM_PROCS == '' ]]; then + NUM_PROCS=4 +fi + + +# Returns 0 if current docker image exists. +function check_if_docker_image_exists { + images=`docker image ls | egrep "$IMAGE_NAME[[:space:]]+$IMAGE_VERSION"` +} + + +# Compile all version of GnuTLS. +function compile_gnutls_all { + compile_gnutls '3.6.11.1' +} + + +# Compile all versions of OpenSSL. +function compile_openssl_all { + compile_openssl '1.0.0' + compile_openssl '1.0.2' + compile_openssl '1.1.1' +} + + +# Compile a specific version of OpenSSL. +function compile_openssl { + version=$1 + + git_tag= + compile_args= + precompile_command= + output_dir= + compile_num_procs=$NUM_PROCS + if [[ $version == '1.0.0' ]]; then + git_tag="OpenSSL_1_0_0-stable" + compile_args="enable-weak-ssl-ciphers enable-ssl2 zlib no-shared" + precompile_command="make depend" + output_dir="openssl_v1.0.0_dir" + compile_num_procs=1 # Compilation randomly fails when done in parallel. + elif [[ $version == '1.0.2' ]]; then + git_tag="OpenSSL_1_0_2-stable" + compile_args="enable-weak-ssl-ciphers enable-ssl2 zlib" + precompile_command="make depend" + output_dir="openssl_v1.0.2_dir" + elif [[ $version == '1.1.1' ]]; then + git_tag="OpenSSL_1_1_1-stable" + compile_args="enable-weak-ssl-ciphers no-shared zlib" + output_dir="openssl_v1.1.1_dir" + else + echo -e "${REDB}Error: OpenSSL v${version} is unknown!${CLR}" + exit 1 + fi + + # Download OpenSSL from github. + echo -e "\n${YELLOWB}Downloading OpenSSL v${version}...${CLR}\n" + git clone --depth 1 -b $git_tag https://github.com/openssl/openssl/ $output_dir + + # Configure and compile it. + echo -e "\n\n${YELLOWB}Compiling OpenSSL v${version} with \"-j ${compile_num_procs}\"...${CLR}" + pushd $output_dir + ./config $compile_args + if [[ $precompile_command != '' ]]; then $precompile_command; fi + make -j $compile_num_procs + + # Ensure that the 'openssl' command-line tool was built. + if [[ ! -f "apps/openssl" ]]; then + echo -e "${REDB}Error: compilation failed! apps/openssl not found.${CLR}\n\nStrangely, sometimes OpenSSL v1.0.0 fails for no reason; simply running this script again and changing nothing fixes the problem.\n\n" + exit 1 + fi + + # Copy the 'openssl' app to the top-level docker building dir as, e.g. 'openssl_prog_v1.0.0'. Then we can delete the source code directory and move on. + cp "apps/openssl" "../openssl_prog_v${version}" + popd + + # Delete the source code directory now that we built the 'openssl' tool and moved it out. + rm -rf $output_dir + echo -e "\n\n${YELLOWB}Compilation of v${version} finished.${CLR}\n\n" +} + + +# Compile a specific version of GnuTLS. +function compile_gnutls { + gnutls_version=$1 + + gnutls_url= + nettle_url= + gnutls_expected_sha256= + nettle_expected_sha256= + gnutls_filename= + nettle_filename= + gnutls_source_dir= + nettle_source_dir= + nettle_version= + compile_num_procs=$NUM_PROCS + compile_nettle=0 + if [[ $gnutls_version == '3.6.11.1' ]]; then + gnutls_url=https://www.gnupg.org/ftp/gcrypt/gnutls/v3.6/gnutls-3.6.11.1.tar.xz + gnutls_expected_sha256=fbba12f3db9a55dbf027e14111755817ec44b57eabec3e8089aac8ac6f533cf8 + gnutls_filename=gnutls-3.6.11.1.tar.xz + gnutls_source_dir=gnutls-3.6.11.1 + nettle_version=3.5.1 + nettle_url=https://ftp.gnu.org/gnu/nettle/nettle-3.5.1.tar.gz + nettle_expected_sha256=75cca1998761b02e16f2db56da52992aef622bf55a3b45ec538bc2eedadc9419 + nettle_filename=nettle-3.5.1.tar.gz + nettle_source_dir=nettle-3.5.1 + compile_nettle=1 + else + echo -e "${REDB}Error: GnuTLS v${gnutls_version} is unknown!${CLR}" + exit 1 + fi + + # Download GnuTLS. + echo -e "\n${YELLOWB}Downloading GnuTLS v${gnutls_version}...${CLR}\n" + wget $gnutls_url + + # Download nettle. + echo -e "\n${YELLOWB}Downloading nettle library v${nettle_version}...${CLR}\n" + wget $nettle_url + + # Check the SHA256 hashes. + gnutls_actual_sha256=`sha256sum ${gnutls_filename} | cut -f1 -d" "` + nettle_actual_sha256=`sha256sum ${nettle_filename} | cut -f1 -d" "` + + if [[ ($gnutls_actual_sha256 != $gnutls_expected_sha256) || ($nettle_actual_sha256 != $nettle_expected_sha256) ]]; then + echo -e "${REDB}GnuTLS/nettle actual hashes differ from expected hashes! ${CLR}\n" + echo -e "\tGnuTLS expected hash: ${gnutls_expected_sha256}\n" + echo -e "\tGnuTLS actual hash: ${gnutls_actual_sha256}\n" + echo -e "\tnettle expected hash: ${nettle_expected_sha256}\n" + echo -e "\tnettle actual hash: ${nettle_actual_sha256}\n\n" + exit 1 + else + echo -e "${GREEN}Hashes verified.${CLR}\n" + fi + + tar xJf $gnutls_filename + + if [[ $compile_nettle == 1 ]]; then + tar xzf $nettle_filename + mv $nettle_source_dir nettle + + # Configure and compile nettle. + echo -e "\n\n${YELLOWB}Compiling nettle v${nettle_version} with \"-j ${compile_num_procs}\"...${CLR}" + pushd nettle + ./configure && make -j $compile_num_procs + + if [[ ! -f libnettle.so || ! -f libhogweed.so ]]; then + echo -e "${REDB}Error: compilation failed! libnettle.so and/or libhogweed.so not found.${CLR}" + exit 1 + fi + popd + fi + + # Configure and compile GnuTLS. + echo -e "\n\n${YELLOWB}Compiling GnuTLS v${gnutls_version} with \"-j ${compile_num_procs}\"...${CLR}" + pushd $gnutls_source_dir + nettle_source_dir_abs=`readlink -m ../nettle` + nettle_parent_dir=`readlink -m ..` + NETTLE_CFLAGS=-I${nettle_parent_dir} NETTLE_LIBS="-L${nettle_source_dir_abs} -lnettle" HOGWEED_CFLAGS=-I${nettle_parent_dir} HOGWEED_LIBS="-L${nettle_source_dir_abs} -lhogweed" ./configure --with-included-libtasn1 --with-included-unistring --without-p11-kit --disable-guile + make CFLAGS=-I${nettle_parent_dir} LDFLAGS="-L${nettle_source_dir_abs} -lhogweed -lnettle" -j $compile_num_procs + + # Ensure that the gnutls-serv and gnutls-cli tools were built + if [[ (! -f "src/.libs/gnutls-cli") || (! -f "src/.libs/gnutls-serv") ]]; then + echo -e "${REDB}Error: compilation failed! gnutls-cli and/or gnutls-serv not found.${CLR}\n" + exit 1 + fi + + # Copy the gnutls-cli and gnutls-serv apps to the top-level docker building dir as, e.g. 'gnutls-cli-v3.6.11.1'. Then we can delete the source code directory and move on. + cp "lib/.libs/libgnutls.so" "../libgnutls.so.30" + cp "src/.libs/gnutls-cli" "../gnutls-cli-v${gnutls_version}" + cp "src/.libs/gnutls-serv" "../gnutls-serv-v${gnutls_version}" + cp "${nettle_source_dir_abs}/libhogweed.so" "../libhogweed.so.5" + cp "${nettle_source_dir_abs}/libnettle.so" "../libnettle.so.7" + popd + + + # Delete the source code directory now that we built the tools and moved them out. + rm -rf ${gnutls_source_dir} + echo -e "\n\n${YELLOWB}Compilation of GnuTLS v${gnutls_version} finished.${CLR}\n\n" +} + + +# Creates a new docker image. +function create_docker_image { + # Create a new temporary directory. + TMP_DIR=`mktemp -d /tmp/sslscan-docker-XXXXXXXXXX` + + # Copy the Dockerfile and all files in the test/docker/ dir to our new temp directory. + find docker_test -maxdepth 1 -type f | xargs cp -t $TMP_DIR + + # Make the temp directory our working directory for the duration of the build + # process. + pushd $TMP_DIR > /dev/null + + # Compile the versions of OpenSSL. + compile_openssl_all + + # Compile the versions of GnuTLS. + compile_gnutls_all + + # Now build the docker image! + echo -e "${YELLOWB}Creating docker image...${CLR}" + docker build --tag $IMAGE_NAME:$IMAGE_VERSION . + echo -e "${YELLOWB}Docker image creation complete.${CLR}" + + popd > /dev/null + rm -rf $TMP_DIR +} + + +# Runs all tests with the debug flag disabled. +function run_tests { + run_test_1 "0" + run_test_2 "0" + run_test_3 "0" + run_test_4 "0" + run_test_5 "0" + run_test_6 "0" + run_test_7 "0" + run_test_8 "0" + run_test_9 "0" + run_test_10 "0" + run_test_11 "0" + run_test_12 "0" + run_test_13 "0" + run_test_14 "0" + run_test_15 "0" + run_test_16 "0" + run_test_17 "0" + run_test_18 "0" +} + + +# Mostly default v1.0.2 (SSLv3, TLSv1.0, TLSv1.1, TLSv1.2) +function run_test_1 { + run_test $1 '1' "/openssl_v1.0.2/openssl s_server -accept 443 -dhparam /etc/ssl/dhparams_2048.pem -key /etc/ssl/key_2048.pem -cert /etc/ssl/cert_2048.crt" "" +} + + +# SSLv2 with 1024-bit certificate & DH parameters. +function run_test_2 { + run_test $1 '2' "/openssl_v1.0.2/openssl s_server -ssl2 -accept 443 -dhparam /etc/ssl/dhparams_1024.pem -key /etc/ssl/key_1024.pem -cert /etc/ssl/cert_1024.crt" "" +} + + +# SSLv3 with 1024-bit certificate & DH parameters. +function run_test_3 { + run_test $1 '3' "/openssl_v1.0.2/openssl s_server -ssl3 -accept 443 -dhparam /etc/ssl/dhparams_1024.pem -key /etc/ssl/key_1024.pem -cert /etc/ssl/cert_1024.crt" "" +} + + +# Mostly default v1.1.1. +function run_test_4 { + run_test $1 '4' "/openssl_v1.1.1/openssl s_server -accept 443 -dhparam /etc/ssl/dhparams_3072.pem -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt" "" +} + + +# All ciphers with SSLv2 through TLSv1.2 with 1024-bit certificate & DH parameters. +function run_test_5 { + run_test $1 '5' "/openssl_v1.0.2/openssl s_server -cipher ALL -accept 443 -dhparam /etc/ssl/dhparams_1024.pem -key /etc/ssl/key_1024.pem -cert /etc/ssl/cert_1024.crt" "" +} + + +# TLSv1.3 with all ciphers. +function run_test_6 { + run_test $1 '6' "/openssl_v1.1.1/openssl s_server -tls1_3 -ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256 -accept 443 -dhparam /etc/ssl/dhparams_3072.pem -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt" "" +} + + +# Default v1.0.0. +function run_test_7 { + run_test $1 '7' "/openssl_v1.0.0/openssl s_server -accept 443 -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt" "" +} + + +# v1.0.0 with 'ALL:eNULL' ciphers. +function run_test_8 { + run_test $1 '8' "/openssl_v1.0.0/openssl s_server -accept 443 -cipher ALL:eNULL -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt" "" +} + + +# Runs nginx with client certificate checking (signed by the CA in docker_test/ca_cert.pem). sslscan will connect and make an HTTP request (--http). The HTTP response code should be 200 to signify that the certificate was accepted. Otherwise, nginx returns HTTP code 400 if no client certificates were presented. +function run_test_9 { + run_test $1 '9' "/usr/sbin/nginx -c /etc/nginx/nginx_test9.conf" "--no-fallback --no-renegotiation --no-compression --no-heartbleed --certs=docker_test/cert_3072.crt --pk=docker_test/key_3072.pem --http" +} + + +# Runs nginx with client certificate checking, just as above. Except this time, we connect with no certificate. The HTTP response code should be "400 Bad Request". +function run_test_10 { + run_test $1 '10' "/usr/sbin/nginx -c /etc/nginx/nginx_test9.conf" "--no-fallback --no-renegotiation --no-compression --no-heartbleed --http" +} + + +# Makes an OCSP request to www.amazon.com. The horrible Perl command that comes after it will filter out the timestamps and other variable data from the response, otherwise the diff would fail. +function run_test_11 { + run_test_internet '11' "./sslscan --ocsp --no-ciphersuites --no-fallback --no-renegotiation --no-compression --no-heartbleed --no-check-certificate --no-groups --no-sigs www.amazon.com | perl -pe 'BEGIN{undef $/;} s/Connected to .+?$/Connected to\033[0m/smg; s/Responder Id: .+?$/Responder Id:/smg; s/Produced At: .+?$/Produced At:/smg; s/Hash Algorithm: .+?$/Hash Algorithm:/smg; s/Issuer Name Hash: .+?$/Issuer Name Hash:/smg; s/Issuer Key Hash: .+?$/Issuer Key Hash:/smg; s/Serial Number: .+?$/Serial Number:/smg; s/This Update: .+?$/This Update:/smg; s/Next Update: .+?$/Next Update:/smg; s/Response Single Extensions:.+?\n\n/\n\n/smg;'" +} + + +# 512-bit DH, 512-bit RSA key with MD5 signature. +function run_test_12 { + run_test $1 '12' "/openssl_v1.0.0/openssl s_server -accept 443 -dhparam /etc/ssl/dhparams_512.pem -key /etc/ssl/key_512.pem -cert /etc/ssl/cert_512.crt" "" +} + + +# Default GnuTLS. +function run_test_13 { + run_test $1 '13' "/gnutls-3.6.11.1/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_3072.crt --x509keyfile=/etc/ssl/key_3072.pem" "" +} + + +# GnuTLS with only TLSv1.2 and TLSv1.3, and secp521r1 and ffdhe8192 groups. +function run_test_14 { + run_test $1 '14' "/gnutls-3.6.11.1/gnutls-serv -p 443 --priority=NORMAL:-VERS-TLS1.1:-VERS-TLS1.0:-GROUP-X25519:-GROUP-SECP256R1:-GROUP-SECP384R1:-GROUP-FFDHE2048:-GROUP-FFDHE3072:-GROUP-FFDHE4096:-GROUP-FFDHE6144 --x509certfile=/etc/ssl/cert_3072.crt --x509keyfile=/etc/ssl/key_3072.pem" "" +} + + +# GnuTLS with an ECDSA certificate (secp256r1 / NIST P-256). +function run_test_15 { + run_test $1 '15' "/gnutls-3.6.11.1/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_ecdsa_prime256v1.crt --x509keyfile=/etc/ssl/key_ecdsa_prime256v1.pem" "" +} + + +# OpenSSL v1.0.2, TLSv1.2 with sect163k1 curve only. +function run_test_16 { + run_test $1 '16' "/openssl_v1.0.2/openssl s_server -accept 443 -tls1_2 -named_curve sect163k1 -cert /etc/ssl/cert_1024.crt -key /etc/ssl/key_1024.pem" "" +} + + +# OpenSSL v1.1.1, TLSv1.2 with brainpoolP512r1 curve only. +function run_test_17 { + run_test $1 '17' "/openssl_v1.1.1/openssl s_server -accept 443 -tls1_2 -named_curve brainpoolP512r1 -cert /etc/ssl/cert_1024.crt -key /etc/ssl/key_1024.pem" "" +} + + +# TLSv1.2 with ECDSA-SHA1 signature only. +function run_test_18 { + run_test $1 '18' "/gnutls-3.6.11.1/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_ecdsa_prime256v1.crt --x509keyfile=/etc/ssl/key_ecdsa_prime256v1.pem --priority=NONE:-VERS-TLS1.0:-VERS-TLS1.1:+VERS-TLS1.2:-VERS-TLS1.3:+MAC-ALL:+GROUP-ALL:+SIGN-ECDSA-SHA1:+COMP-NULL:+CTYPE-SRV-ALL:+KX-ALL:+CHACHA20-POLY1305:+CAMELLIA-128-GCM:+AES-128-GCM" "" +} + + +# Run a test. Set the first argument to '1' to enable test debugging. +# Second argument is the test number to run. Third argument is the executable and +# its args to be run inside the container.. +function run_test { + debug=$1 + test_number=$2 + server_exec=$3 + sslscan_additional_args=$4 + + test_result_stdout="${TEST_RESULT_DIR}/test_${test_number}.txt" + expected_result_stdout="docker_test/expected_output/test_${test_number}.txt" + + # Run the container in the background. Route port 4443 on the outside to port 443 on the inside. + cid=`docker run -d -p 4443:443 -t ${IMAGE_NAME}:${IMAGE_VERSION} ${server_exec}` + if [[ $? != 0 ]]; then + echo -e "${REDB}Failed to run docker image! (exit code: $?)${CLR}" + exit 1 + fi + + # If debugging is enabled, just run the container. Don't do any output comparison. + if [[ $debug == 1 ]]; then + echo -e "\nExecuted in container: ${server_exec}\n\nTerminate container with: docker container stop -t 0 ${cid}\n\nHint: run sslscan against localhost on port 4443, not 443.\n" + return + fi + + # Wait 250ms to ensure that the services in the container are fully initialized. + sleep 0.25 + + # Run sslscan and cut out the first two lines. Those contain the version number + # and local version of OpenSSL, which can change over time (and when they do, this + # would break the test if they were left in). + ./sslscan $sslscan_additional_args 127.0.0.1:4443 | tail -n +3 > $test_result_stdout + if [[ $? != 0 ]]; then + echo -e "${REDB}Failed to run sslscan! (exit code: $?)${CLR}" + docker container stop -t 0 $cid > /dev/null + exit 1 + fi + + # Stop the container now that we captured the sslscan output. + docker container stop -t 0 $cid > /dev/null + if [[ $? != 0 ]]; then + echo -e "${REDB}Failed to stop docker container ${cid}! (exit code: $?)${CLR}" + exit 1 + fi + + # If the expected output file doesn't exist, give the user all the info we have so they can fix this. + if [[ ! -f ${expected_result_stdout} ]]; then + test_result_stdout_actual=`cat ${test_result_stdout}` + echo -e "\n${REDB}Error:${CLR} expected output file for test #${test_number} not found (${expected_result_stdout}). Actual test result is below. Manually verify that this output is correct; if so, then copy it to the expected test file path with:\n\n $ cp ${test_result_stdout} ${expected_result_stdout}\n\n------\n${test_result_stdout_actual}\n" + all_passed=0 + return + fi + + # Compare the actual output to the expected output. Any discrepency results in test failure. + diff=`diff -u ${expected_result_stdout} ${test_result_stdout}` + if [[ $? != 0 ]]; then + echo -e "Test #${test_number} ${REDB}FAILED${CLR}.\n\n${diff}\n" + all_passed=0 + return + fi + + echo -e "Test #${test_number} ${GREEN}passed${CLR}." +} + + +# Instead of spinning up a docker instance, this will run a test using a host on the +# public Internet. +function run_test_internet { + test_number=$1 + command=$2 + + test_result_stdout="${TEST_RESULT_DIR}/test_${test_number}.txt" + expected_result_stdout="docker_test/expected_output/test_${test_number}.txt" + + `/bin/bash -c "${command} | tail -n +3 > ${test_result_stdout}"` + if [[ $? != 0 ]]; then + echo -e "${REDB}Failed to run sslscan! (exit code: $?)${CLR}" + docker container stop -t 0 $cid > /dev/null + exit 1 + fi + + # If the expected output file doesn't exist, give the user all the info we have so they can fix this. + if [[ ! -f ${expected_result_stdout} ]]; then + test_result_stdout_actual=`cat ${test_result_stdout}` + echo -e "\n${REDB}Error:${CLR} expected output file for test #${test_number} not found (${expected_result_stdout}). Actual test result is below. Manually verify that this output is correct; if so, then copy it to the expected test file path with:\n\n $ cp ${test_result_stdout} ${expected_result_stdout}\n\n------\n${test_result_stdout_actual}\n" + exit 1 + fi + + # Compare the actual output to the expected output. Any discrepency results in test failure. + diff=`diff -u ${expected_result_stdout} ${test_result_stdout}` + if [[ $? != 0 ]]; then + echo -e "Test #${test_number} ${REDB}FAILED${CLR}.\n\n${diff}\n" + exit 1 + fi + + echo -e "Test #${test_number} ${GREEN}passed${CLR}." +} + + +# First check if docker is functional. +docker version > /dev/null +if [[ $? != 0 ]]; then + echo -e "${REDB}Error: 'docker version' command failed (error code: $?). Is docker installed and functioning?${CLR}" + exit 1 +fi + +is_debian=0 +is_arch=0 + +# If dpkg exists, assume this is a Debian-based system. +dpkg --version > /dev/null 2>&1 +if [[ $? == 0 ]]; then + is_debian=1 +fi + +# If pacman exists, assume this is an Arch system. +pacman --version > /dev/null 2>&1 +if [[ ($is_debian == 0) && ($? == 0) ]]; then + is_arch=1 +fi + +# Ensure that the libgmp-dev, m4, and wget packages are installed. Use dpkg on Debian, or pacman on Arch. +if [[ $is_debian == 1 ]]; then + dpkg -l libgmp-dev m4 perl wget > /dev/null 2>&1 + if [[ $? != 0 ]]; then + echo -e "${REDB}Error: libgmp-dev, m4, perl and/or wget packages not installed. Fix with: apt install libgmp-dev m4 perl wget${CLR}" + exit 1 + fi +elif [[ $is_arch == 1 ]]; then + pacman -Qi gmp m4 perl wget > /dev/null 2>&1 + if [[ $? != 0 ]]; then + echo -e "${REDB}Error: gmp, m4, perl and/or wget packages not installed. Fix with: pacman -S gmp m4 perl wget${CLR}" + exit 1 + fi +fi + +# Make sure sslscan has been built. +if [[ ! -f sslscan ]]; then + echo -e "${REDB}Error: sslscan executable not found. Build it first!${CLR}" + exit 1 +fi + +# If the user specified a test number to debug... +debug_test_number=0 +if [[ $# == 1 ]]; then + debug_test_number=$1 + debug_test_number=$((debug_test_number + 0)) # Effectively, convert this to a number. +fi + +# Check if the docker image is the most up-to-date version. If not, create it. +check_if_docker_image_exists +if [[ $? == 0 ]]; then + echo -e "\n${GREEN}Docker image $IMAGE_NAME:$IMAGE_VERSION already exists.${CLR}" +else + echo -e "\nCreating docker image $IMAGE_NAME:$IMAGE_VERSION..." + create_docker_image + echo -e "\n${GREEN}Done creating docker image!${CLR}" +fi + +# Create a temporary directory to write test results to. +TEST_RESULT_DIR=`mktemp -d /tmp/sslscan_test-results_XXXXXXXXXX` + +# If the user wants to run a specific test with debugging enabled, do that then exit. +if [[ $debug_test_number > 0 ]]; then + eval "run_test_${debug_test_number} 1" + exit 0 +fi + +# Now run all the tests. +echo -e "\nRunning all tests..." +run_tests + +if [[ $all_passed == 1 ]]; then + echo -e "\n${GREENB}ALL TESTS PASS!${CLR}\n" + rm -rf $TEST_RESULT_DIR + exit 0 +else + echo -e "\n\n${YELLOWB}!! SOME TESTS FAILED !!${CLR}\n\n" + exit 1 +fi diff --git a/docker_test/Dockerfile b/docker_test/Dockerfile new file mode 100644 index 0000000..6e0d0d7 --- /dev/null +++ b/docker_test/Dockerfile @@ -0,0 +1,31 @@ +FROM ubuntu:18.04 + +# Copy OpenSSL's 'openssl' tools. +COPY openssl_prog_v1.0.0 /openssl_v1.0.0/openssl +COPY openssl_prog_v1.0.2 /openssl_v1.0.2/openssl +COPY openssl_prog_v1.1.1 /openssl_v1.1.1/openssl + +# Copy GnuTLS client & server tools, along with their required libraries. +COPY gnutls-cli-v3.6.11.1 /gnutls-3.6.11.1/gnutls-cli +COPY gnutls-serv-v3.6.11.1 /gnutls-3.6.11.1/gnutls-serv +COPY libhogweed.so.5 /usr/lib/ +COPY libnettle.so.7 /usr/lib/ +COPY libgnutls.so.30 /usr/lib/x86_64-linux-gnu/ + +# Copy certificates, keys, and DH parameters. +COPY *.pem /etc/ssl/ +COPY *.crt /etc/ssl/ + +# Copy nginx site configurations & modules. +COPY nginx_site_client_cert_required /etc/nginx/sites-available/ +COPY nginx_test9.conf /etc/nginx/ + +# Install nginx for some tests. +# Install strace for potential debugging, and rsyslog to enable system log gathering. +RUN apt update 2> /dev/null +RUN apt install -y nginx strace rsyslog ca-certificates 2> /dev/null +RUN apt clean 2> /dev/null + +RUN update-ca-certificates + +EXPOSE 443 diff --git a/docker_test/ca_cert.pem b/docker_test/ca_cert.pem new file mode 100644 index 0000000..3b7ae16 --- /dev/null +++ b/docker_test/ca_cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFUTCCAzmgAwIBAgIJAI+xjVeRdKcWMA0GCSqGSIb3DQEBCwUAMD8xCzAJBgNV +BAYTAlhYMR4wHAYDVQQIDBVOb3doZXJlIGluIHBhcnRpY3VsYXIxEDAOBgNVBAcM +B05vd2hlcmUwHhcNMTkxMjAzMDIxNjUzWhcNMjkxMjAzMDIxNjUzWjA/MQswCQYD +VQQGEwJYWDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQH +DAdOb3doZXJlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAze8SR6JK +HTftNJrZdnvzE5LlpU6hCVGr1aIhx1nWae7crLRRB7xAc9T+YIMUhMazKwbMJBIx +7I6rYeU+FWJBkcc5AREk0C1sM6vlM001kpcYs3amib1DTJkORdQTJlh5+bPlnupa +YJQIqAVKqnEYUJuOblpeUqz2LteVLlV1hycznrvkmywU72AtzaOTx1hrgH7FjpVz +2M2KJ3zDFO8NfDtqx67fbM8Z/QL+/67tfSFwRKdPU4u38IlushoYbQ/8Y81Hw1tQ +2px08q2awgtFljHl2cDLsDB8bAsQ+AiU9/3trbTid1U48Q8Uk0BBJ+TXio5qDg+n +bPw0gcXlq+Rj8CBADPzWaBZdAtH1kVlSwJ2PZ5xwi0LKNsJN2wbfJIc6WjA/pL5p +VjS+Yx5X8rhGqWAJDrbLoVoTg/bEy8RPPorxBspFe8jPRoSIWsmDZn+SL0SbgnxV +eZG0tVn6nbWepSUOq23Gc9E6sfMsMR3WxBBIchoWCkPB8Y/X0YeT0V3kGql2fVsT +6mMTTDvcc4RORikH+wg0EOmzn+WA0I5BzR2zYANfga+cPuowO+U6qf85wzeO6eDp +x49GAyTCGMYlhZd/hWEXD+Q2bZRy2j8osTRe270MKyYiMuP0eB7VZx7pr1zb8fTE +BAh4JI6xUqCG8isoTyEKDdLrX4ilW+ZN2tkCAwEAAaNQME4wHQYDVR0OBBYEFDTe +OueTIjWF4f771PS5kGNY28BLMB8GA1UdIwQYMBaAFDTeOueTIjWF4f771PS5kGNY +28BLMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBALnZCFWzH3n0GFpO +fYxALeoyrwYia4HrGGQ9JOwQJEHH1sUL3TwvGVoLtSB8962loGakvhtwvtr6XDyk +wqsAF9J1j7PKzXvlVt3MAGDupDMTgOvX9D7GY/MYhteB2ExckmDXGyq/Ustm877S +XaEkwiwCs2Jrm9T6ksZIcFd0OwpzfY+sEBjmKKTKo6n0xOmUEvlIsJ8AHZg0cOsj +LD0hdcdwQ6gtvX+LrjrCWk1OzjHlGWLpDuPhDlhYFidBoRH65SWjUzqH6jmaUjEi +pwO3wmPfaXAkSqVw1O+Pkc0BThpSbPCwnn5J6VuAJQN65pLD1vRh0UfpLI8TeOQe +dDDIoiRjRCrBfSmrzZ5uj18fC/MB/6x5jfyPzMMlJCSmpWcuz65imP8VVn8V8M9b +vGM+hgP66xEO4UwBGbKiIWh8Hb0Jqo+vV6AObdpncOmWxnFU891NbyLjgkRfmTMq +dH3q71sarOmvv2aHcZTWwj46mzPoJHViS0lT3XYURTKar16RgMihUmKcMyPdVj75 +JDZyvJwpis3zSPTERmYjeuqY3Lb/hXIWHMg3v6+xWrHunj7aFuugCtyl2qm6uHGh +5uBjZfocr+ZrT4YItUZGsSw4zfkJMIWVuHuX30Q2Gtrkt25IlYCKHZGpb49KyWub +wS03DVRaHGOd/8zksngsXzReZeor +-----END CERTIFICATE----- diff --git a/docker_test/ca_key.pem b/docker_test/ca_key.pem new file mode 100644 index 0000000..d4e80af --- /dev/null +++ b/docker_test/ca_key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDN7xJHokodN+00 +mtl2e/MTkuWlTqEJUavVoiHHWdZp7tystFEHvEBz1P5ggxSExrMrBswkEjHsjqth +5T4VYkGRxzkBESTQLWwzq+UzTTWSlxizdqaJvUNMmQ5F1BMmWHn5s+We6lpglAio +BUqqcRhQm45uWl5SrPYu15UuVXWHJzOeu+SbLBTvYC3No5PHWGuAfsWOlXPYzYon +fMMU7w18O2rHrt9szxn9Av7/ru19IXBEp09Ti7fwiW6yGhhtD/xjzUfDW1DanHTy +rZrCC0WWMeXZwMuwMHxsCxD4CJT3/e2ttOJ3VTjxDxSTQEEn5NeKjmoOD6ds/DSB +xeWr5GPwIEAM/NZoFl0C0fWRWVLAnY9nnHCLQso2wk3bBt8khzpaMD+kvmlWNL5j +HlfyuEapYAkOtsuhWhOD9sTLxE8+ivEGykV7yM9GhIhayYNmf5IvRJuCfFV5kbS1 +WfqdtZ6lJQ6rbcZz0Tqx8ywxHdbEEEhyGhYKQ8Hxj9fRh5PRXeQaqXZ9WxPqYxNM +O9xzhE5GKQf7CDQQ6bOf5YDQjkHNHbNgA1+Br5w+6jA75Tqp/znDN47p4OnHj0YD +JMIYxiWFl3+FYRcP5DZtlHLaPyixNF7bvQwrJiIy4/R4HtVnHumvXNvx9MQECHgk +jrFSoIbyKyhPIQoN0utfiKVb5k3a2QIDAQABAoICAGMM1HwEASXgmoUs3d/xak9F +3pMOKMK0t7O/kgOyoEC/lQC0kizoTQ/pqJh/M8VRVSgi0tmersibLq+ddakPY35c +lnx+5HgFAQAxc8KjJltltYnMTfn+QHp9O7I2eSd+cty5vH4dNm8xhKBcOzeTwiAz +UeSeLrQRYS/SnXx1ulvRbTCyKxi/sSoZ1q4MOa4uRza8wwT7uYbUBdlMVwCgopnY +clmtMOXDDzr0z/XnC2+eP8Olva/vif91+vpLNuhuQfU27Yd3SoJ7snxvJ/qhNU0y +nt2Hr/EEwTOudvD2H8DQMBvW3v6KzSKVIE5bH3uyxEFuknBE80CmZhLtPrTY23/s +97/ncS+tY3mxr8hOBRyiz7o2zDvPcbSq56jt2JkUUS4mwk2uVzpO9uKhrDY9CkkS +Iq5UjV0gtjQ8092Mp83Bazy0q7fTKdwgvsoorbdKMZP4GZ0EPIGJC9r8IH9UD7Cl +1YVGj1qBXUFznbJmFtNGofvc/8PzZ6TMNscEVOcjy8vrqmhKGcdXMoMl1LxDl/4g +mN26n9uKfatCeRN9qyxOsts3+QEqJq+rKn2odQlCNfpezxNh8uauAx8ZxQ4HXirW +O+CZS5JAlNWK5qp27pGq7JNKy5xyaU8PkC5G/A8Fi35iF1o0j2ICSWkCY3cTd73W +/TvzsGNsbrJLTIFfo1ghAoIBAQDqOp7LfXLZct17TdpBSwq+2IzSN/H6ozKcyXSf +Nnx56Avy1OZkU3ELMN+/zZp9X91dhR+PpXJfcbufiuJIUq0L34ow8X+cnw66hUur +ig9rzs7o1Ak6PZcrVINOjZ5Sn6gzuDMZgH5PzFNjXxZto1KjDLCnf5adoYEUfjJZ +r85ZN9/NlUW/PhZzuyRUW0ouRDsjjnLQouomCrFbva2tvpPggCcRlizHg6ReyX1S +LfozmQbfvI4e60cbRj5MuouJbbvMicecRT5R00HhTfHTj5MMqf5DRToS2ir/QYw6 +kZQWHdFih+eDQcZFiPILUxq89OSBJy2UtrfgaFxGiPBdgm5lAoIBAQDhEy5NBB0X +udTc9BJlL/ROp84/ER/OTd4eG57FVXhv/kuC+v2gv/M+PHc7RVSZCh+sEvqs2Dzd +qRms57zQGJ2zbSzhgcCzghpNx+mNXe5UScAUM4sDONOGeeQc15HkAMCz4/umcInc +IcM1zsbxa+AG8YGv9JHuknYBZ2bbaUlsoltQ57sa2h7Wht3ql3IRYSu2hwsWiGlb +MZlozaEXpqH4+LvBfs0gCXNmqMOV72MnEFWFVooSzISi5KakPysH5TNypJpE6FWn +1ccUMTFFkNRFgn64qUXHyaKQlaMl0UPb3XVcyxB4Wamde8yXoo4trdFRGY1kRLl9 +31zFeZDoT8llAoIBAQDGV61wE2LVz/bNGzfeYnVO9oEI4mb+HoQVUGJ5D+KIOH8l +ujL+ccof99sAyFIyKKODNd9r/GXFfMGscCb9p0Tx8PFMULQHJImMWKOjNt2oJRAB +CMxnjRAdmQs30aRnwtrkMO7UgYJ0gEl8tGCBpvOrLmvI6rnX8ZMkj1iDqePKmQ3j +QKw3LZRFnAs/g65lT1Hk4hNHqS0t2ZAmZ5BSuDbwvJRYyBpTOJ5Pxb9hf52HY+X2 +P+z5MbKc3faTcsQGM+37XhCxu9Dx6Tq4VxCYXdPfvXOZ810h6azPSeo9DlmgAM/1 +56+b7m6/IyAThuP1bkqxM0Pd0nwSg0zgTcV86Z4hAoIBAELgYSSPMVnIZMBWYVTh +n9TzNWw12V6Ccpo9mLqHv+Z/B87eZxgpkMwQSVk6K33hrTGC3isXgVZXlYJzxP2M +Iueaa/iBhlGQOeKcoP/ZRiSTWVhnTEnjy64sb6RGRVobAycweailzcCz434Md75q +UEGf5unyYJ4jtJ6MK9rL+P4na7ypbkX3Q6x4nF3FLCaP2d49WAUU+UEYhr3GQ7R0 +VbJVrew7khWP2VNKl/roC20jBFY/NX2KeWqxR/aLsmyBJP1OfWw2IKVi9ulACKTj ++L7CnIaf/VT0y7HsVHK7ME+XCPVOfRFVivl5PHxd16Mo/4X6crG1XexRvw4KJg1x +D6UCggEAT+eKtfA0EkA4zQKAC15KZSTxrpYK0phQX6dBTgwXlwoczInlX7HjtQb9 +7G9OzRFZvenzXsBfT+av1ilSjEPo6l/bL664qJY4hzG+5Tq1NC0YA+2Ihb9/wQP/ +yXp/tnn27XZChm/wxdGG+s7wpWaZ9LQj/80pbMbH/DoMGlaFyHF+8RPXbDF6ycJF +kAV9E0PKeVBGaQbvEx1NW093F1Lf2yPhPeEA89qjmOigyZQ7r4tIhJxYgzUo3gqD +b8PbWwbrGPGD5AUu6V4Fv2E86mIgoRlcZFayHGDvGSqM5CZ7VSLLc9pc33WPV55T +IvfsnBvVJ9M2TPyXcd9tejBOzLjOkQ== +-----END PRIVATE KEY----- diff --git a/docker_test/cert_1024.crt b/docker_test/cert_1024.crt new file mode 100644 index 0000000..a9da5ce --- /dev/null +++ b/docker_test/cert_1024.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDpDCCAYwCCQCaM8BbiyPRSTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJY +WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do +ZXJlMB4XDTE5MTIwMzAzNTY1MloXDTI5MTIwMzAzNTY1MlowbTELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAk5ZMRIwEAYDVQQHDAlSb2NoZXN0ZXIxGTAXBgNVBAoMEEJh +bWJvb3psZWQsIEluYy4xIjAgBgNVBAMMGWhvd2Z1Y2tlZGlzbXlkYXRhYmFzZS5j +b20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOak+uYE1LeCoKAIH2Uq8fhm +lf0W8fPDc/iQ1vI3jn7zKruAFSl/0lgVA7SuqbSFJ5slJBQOSGsV87qidl2wzI3f +aU+VU8WYEgswE+BrElNVQ5r5NbGDJW4+Bp+2sxAyvRa+Fu/7deG3mGo9MQp78YTD +Fcko9KbYXUCACSTCVBHNAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAEh3v+b8P6/g +3OkAzkNpLJ2yQK1AJ35yd9KtmnTWzAYfWqkowWOZPVQv41VG0LEy8DF/DuBlXLyp +H1HfY7hpJYMmZfs1Mdcr1D7pir1nobG7CFJSiS4/R1Irqb4KQhFaYPEvdy6vEh5s +T+DrF6/rWlE1QnoiAoDxgUn7gYv5LThux/aX2L9ne6YY8mxBZm6AXCjsXGSFZdFY +vAFeQTAVs6/lJ5AXrV9IIO5L9MGozeKVKTwz5MqNlQjr2XkGeCJ/+L40NL91/mTK +xuSIZXP3gCyfL+szN7qQ8NWmrqdFoUkzVyV+SUbXfpuVLf+yC7dZGZx8AktqQERr +esKgd54fIJTpZGRtx/y9UW9OAHugAoAd/6Sd1Pk3B2YH4cJPFQTUkod4OKotWs0f +R4DA+aAf0tqFwKRTGDsny/6+nnGenn75zRunmae0R51vS4vbHgEoMVsGLu/QbSdC ++f9DYXpeH96u/0lKl5ueW/Acoa20ngJFS6IzJiWMTJPxWJYq+gOnSMS2OEakoUKU +UYjZ1VFYJrnXB+cKBksY38c6ryskUP1dfaWICwX9DH2MnD1RuuaKcdmhu+k45ujC +LefUCIQ+2K4jMe/Irvk9yAbKfSBZ7xfRfgNPTdr0jjLfSZHhI5QDUOUsP8SEt1yV +CQx1WMxnRCNtwJVsAhisGWFTA0sDImOX +-----END CERTIFICATE----- diff --git a/docker_test/cert_2048.crt b/docker_test/cert_2048.crt new file mode 100644 index 0000000..f671473 --- /dev/null +++ b/docker_test/cert_2048.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEKTCCAhECCQCaM8BbiyPRSDANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJY +WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do +ZXJlMB4XDTE5MTIwMzAzMDEyM1oXDTI5MTIwMzAzMDEyM1owbjELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAk5ZMRIwEAYDVQQHDAlSb2NoZXN0ZXIxGTAXBgNVBAoMEEJh +bWJvb3psZWQsIEluYy4xIzAhBgNVBAMMGndoeXRoZWZ1Y2t3YXNpYnJlYWNoZWQu +Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAywGmJp/AoA4TCs6z +bXuiBOkho35IeVvpsy7RqM3y3KxkEFnk/LM6U/ayL+j2vo4/15WPM0PaAGRRbvnQ +EuI1xvhn/0/T4xP+TBe91pTMo/nKrK/ycvBLBqLPZQK9SJbHk6mwfgpQs5S/+VHl +U9jl7+eQWcR+o3NXtv4XFlQyqx1dcokAJrL4wr2vGPkigUNU2iI6FwRB4f7Wo1rB +NzI49uE97IWuh+VBMPYMp+Zn2Om4ptCyjdvSI7DEYc6jyKlPzH2UOgd0RkcwivaS +pxfXJEBOC8PtOxyLg/KPjUTwUh0nHSpeOIbT3HKnOErEbbiHQmlYbbcOyinv3hIl +Rj+PyQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCYTQPx8JIdeNfov2cSsM/8ByDo +M6DDhW+kAgGdhKdGglDXtrtX4ffPYvG1EjQg7TIZJoXWcwng4XWGFI7lGqyAOQn9 +KjDqfFj00udNJq8B57JJK3vq71rppcggt5mJnzTrrMlTZ4z8ZMFLnj6drCEsjZLM +3oRRcBvtfC4j9xT4ZICt8R3eXw18Ne43PT1wRhFpQAud0Y9zPO/0veyAlf/D0suR +8Ix8XXRr3PU+c5XZeY2uT50FcHNKLgcSmck+25CPnwSdQtdhhfcXGpBKzczjHHTU +yqIBVf9xwM4sCtg50aWrdYTYgFivMqPy4ieLe/NlhrlmjSJPFR/hw7605mTiu4zG +9Dlr310eCjL8jiASWpfj27u6QYaxFL5yg1mMfl/mvDr9dLV4LnffdkeE8hk+PVkz +IvHKeLhAu39t1JAs841NwW0WhdxOQkSB+VqDmixy9lmJhM0c8I45S9qERvnKrd9S +kMiVxO0d4Aza1eEt1Kep2tfK2CkAzQD30Tl/v4njPZXR7lU5p4g6pr4EukxBwMrs +t2Hs1Czb9x59HV7FDB0Z8DgrNkysi40lRMMNzNoQ2HaoaLKuotwXZFCs5O5HRnze +iMDS3Jy0gDs53TanmxXC2gE/ODeYOqzkOjvGgPruZOMEZ7bKkLkC/lcUxIYy4xoE +PgE/onpOVIay+K/3dQ== +-----END CERTIFICATE----- diff --git a/docker_test/cert_3072.crt b/docker_test/cert_3072.crt new file mode 100644 index 0000000..abd27be --- /dev/null +++ b/docker_test/cert_3072.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEmTCCAoECCQCaM8BbiyPRSjANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJY +WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do +ZXJlMB4XDTE5MTIwMzA0MDc0M1oXDTI5MTIwMzA0MDc0M1owXjELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAk5ZMRIwEAYDVQQHDAlSb2NoZXN0ZXIxGTAXBgNVBAoMEEJh +bWJvb3psZWQsIEluYy4xEzARBgNVBAMMCmxtZ3RmeS5jb20wggGiMA0GCSqGSIb3 +DQEBAQUAA4IBjwAwggGKAoIBgQDEDVOhDYctVgOYpKM9KUKmixtQxgDfQGVFczN0 +l7U5UGD+rASuFRGUUC8YX2WOBcWcxnqhMrXriwlexyM1dL8BupY72sF4xtTEPzn8 +9Gjh6aYFWKh7kD8DjFsC8+3WyfCCNu1k1OzFmiF5SjHbXr81MnbhzdIYQE6UBIEe +1PpUEk9qbHVoAuVKVLiOq0sCWTHPoz9dQ95ERHoMphdSLfvDRcJlFGTVTa54zad+ +TPjtr8bGh4Baa9Y9VbUG75Vslv0eyH/ai3KEdkBVf39+wpnAd/2pxKu60uTkzSLH +01QWeryplW5ktNlrv+sLDpieaU6/WYBknyw0m23XDKEwYt5uR9UcoREKqTfstGlL +OWhO73n64+7+r7f3VcwpM6YwerCG9kGkCg683tuzijw3UkXyE+74wEaxlSzw/571 +ZMlTb3O85FZ3tn/wrXNqSKEkP0VdwLfw4Y7zyH/slXFhwzJVRlbfNkrEhOUlaXwn +Xw6pClProrhx4s5bVKNEh4cZf1MCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAikFI +8LMptJKl9L5WmXW3OFS/stc0dxBQ/0/qzPiDWrhINrFkIYeNZ2fi+Cv6mLXil+C1 +72Mu9YsTJ6L6VjHUnIXAhwQC4gjnhjPoZIQ3sdaQl0I5vwPr5xS6wDLoWtUSjcem +x8x+axPEsqw/EIGv55NsY7YezpqFU48rkRrGbJL9jOVbKcIwzbg5ZxqRZ2kmSUD9 +Ze56RqXhwZPbdMmcrIk2632RoAh9HXgndL9QCIvypDnK50KpP/b2C/1Amaux//Rs +ro8C55J/x2FWl0iDwHc4gAtsZvn8aznfGnavj4JHq8+3cZBZQ3zfv6ojFvWCBniT +YGb57CJA+s1MW2urF6ldExgsb/adQN7oXW6I0Y9A+zFOdd3epoa+GJZu2FI7kVs3 +VViioCRPDCCxgDJ8CnhBvr5ALd+dWDGOpU7+POWqmtscF56tnPgiCK9J8TsT2GkN +S5h/NbTbxEZvFAJS5x4GnwQBW0o0tmnybLzkRUeUucDg3k/jsMsnQIft2kPtcxD8 +vEZWKl/jwfX6EMLIXgAHIDK2HiG9301GlksvDTFaZhMNRcH9RYhTwYYsdLjvs5Bj +aY+evRF2E6MQnaLQ7m1Hg8YZZY5O3Z/n6fPUESd3zMSsXtmcyRZ4KP5LSwTy6HuE ++qEu3vdeFaOd+Ii8k8sD/4SuKf7RcXC3OG5Ne0M= +-----END CERTIFICATE----- diff --git a/docker_test/cert_512.crt b/docker_test/cert_512.crt new file mode 100644 index 0000000..604aa48 --- /dev/null +++ b/docker_test/cert_512.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDSjCCATICCQC6PCarUG/VGDANBgkqhkiG9w0BAQQFADA/MQswCQYDVQQGEwJY +WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do +ZXJlMB4XDTE5MTIxMzAzNTYyMloXDTI5MTIxMzAzNTYyMlowVzELMAkGA1UEBhMC +WFgxHjAcBgNVBAgMFU5vd2hlcmUgaW4gcGFydGljdWxhcjEQMA4GA1UEBwwHTm93 +aGVyZTEWMBQGA1UEAwwNZ2VvY2l0aWVzLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sA +MEgCQQDL3c8fl0i1RqSy1ctDSAWVbOpOy8b4ruQspvuZ9M28LGCrYq2pSL3NBz3p +CYpNaP0C4KnDvN/N+8DkvIT1NJPVAgMBAAEwDQYJKoZIhvcNAQEEBQADggIBADgl +k3V0s2HTPreUrn37fNwj9jYlATJGiQEy8tOoU42j6hK1nhVDq947JCtRXN3ykQkp +bGWcK8TioA+IgPopW8as7rPPzbG330LYUqTub4v3r7b8NqMQBJeRp5EbDj7cvppW +L8Op/pKNJBdFCL+qp4vw+k31ZALcDLfU2evGLD5cq7S/FmzQs7es0c13RICPK3nI +X4AC19isu52zzMXXECPL51nbWbVH7MRQt/UPzfgyDfe+UIAUpR/cvGqree/fWL2D +UQrIOD/k789XzrynRfjlJjxeSWlIyrSYD+zedjxUyn+L6YfcEwUfaqvfYn1YOeKZ +BXNNTxWWZQtdlXif1L/Tk0xHrXlpMNJOmXUnKu9Wb/7ovTfjxiXHnwrhmOHZAn6O +e1Oev5tnMmVWEtp0c1uowX4BTKtl5v/a827cTSJDVm5Va+cfIGL0MkjFcPz4zq04 +Ke/22SM4XdEiUvSiiYj/NrTI4txLid0d+gRZZIzoTnybUobBZUFWYvIFqyi990OF +Mnjercyzb5uEpCiq2xZVwAKSUNMzFqzv+zerN3otOwi3lIY1evNkRdGngmmItEUD +wvNgfpQApqAUH81zFKpnCmOIMZ3XDed+xO7JCJKr1zZ6+qyEhtrew8RL2hMHIok0 +jQQ3dyi39Ekmfr+CyKvPBQ+F4qtMHgv7VFd73RBf +-----END CERTIFICATE----- diff --git a/docker_test/cert_ecdsa_prime256v1.crt b/docker_test/cert_ecdsa_prime256v1.crt new file mode 100644 index 0000000..3cd4a48 --- /dev/null +++ b/docker_test/cert_ecdsa_prime256v1.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDVjCCAT4CCQDe1MM22vqmNTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJY +WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do +ZXJlMB4XDTE5MTIyMjE5MDE1NloXDTI5MTIyMjE5MDE1NlowZjELMAkGA1UEBhMC +WFgxHjAcBgNVBAgMFU5vd2hlcmUgaW4gcGFydGljdWxhcjEQMA4GA1UEBwwHTm93 +aGVyZTElMCMGA1UEAwwcaXRzcGVhbnV0YnV0dGVyamVsbHl0aW1lLmNvbTBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABEJG/H34ca87RR7tz4meDGqz8sV+nSSl2+VB +JFW3M3W85C84Tlx5WG5Z16+GtpsK0hBT84wjkUo0KpPfY7/dCFYwDQYJKoZIhvcN +AQELBQADggIBAEATuWgTLHRq3+EDfJj8l5kGhvg8jjAGc/9J1i8oEwJl1Gy8Dv02 +jFu67camK09vprZ25EHzyVHUn+1PtZUi1kl/dpnBfFYADHZTOyokhIZ/QWLd1yr4 +Oc7ZHcVwODt+S/npfZsga2R66oI+wUQbkF7+/xpFU/DcjevMQkE3Ql5cMaFa5NZf +Z7adpYct7RPTW1aqPVckZbB3FfN85YpTyRVOt3u93/qG73dzIVjVg6YsjZYgtvxD +QhIQotKyAL6lIzA51KtIY0WhE2QmBB4YnIHlK1VkvvTaWk5tcBuY8Se2mBHfAyL5 +TESNfxBi884xBoHAJXkV6tZszhEJFgJi7zZS+fpP3kxst+CQBvhSa7gh6hWcqZyL +JGCUTjSUxfZEo97cKqOt8kYMls1eBYuIOUQdmcFbY8ML3O90KpLxosT9cUwsceZc +nBnF1qJwtG0o1RsnAYOLVCuZaimqor7rBGgBwBjkauR58PgQQBvMLtwj59edkkW+ +fAQ/xcI7ofETEKzoxHc1ea6LTE4ELWP58tds5URx0/aGYyMVazKZyhPDk2rh7/r3 +uo7rhOrCJBO89u7wRcbSnzxtWxYI3V8+5a/70Eh7ztIUJwOd+XehexJJvqZdeA7p +LBMjnUSNaR1BA4oNXP3vaFUgRFDf8dosmVAstzVDHQlE6l08bFZ0ovpj +-----END CERTIFICATE----- diff --git a/docker_test/dhparams_1024.pem b/docker_test/dhparams_1024.pem new file mode 100644 index 0000000..5fbcf87 --- /dev/null +++ b/docker_test/dhparams_1024.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAOA34y/7fH82VEhOGbr50PFlSTZcVG5+YtJmVsWH+r6Y72UAIyhBbF2D +ll4gK+uYmXam6Uk8Nwf1U4QiLf7H6ZWlk3ynTa0XUWAGDf8Fce/Y9bWaJV+M7Klr +c+WGk/Rt8CySRfB58fzsoGuDEW85tq5rqlkJcIKBr2bgSTtE8kIrAgEC +-----END DH PARAMETERS----- diff --git a/docker_test/dhparams_2048.pem b/docker_test/dhparams_2048.pem new file mode 100644 index 0000000..8d29550 --- /dev/null +++ b/docker_test/dhparams_2048.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAhmyrz3SekFJY9nkmUt7tKXi/fNfxw3/UZA9+g0SOsvYxMI+vw8XJ +ILm+8HJR5+kvcz6vkxgbxV9IACEdRzf33zBHcRXzA7OifsAy8CN217d8HNHqurGk +ueCLTn2w1SfMy2Do3NB50AOru32xPBQL9hqLLhqEs8IKdAVuNL/OKmuLCovaAck4 +YYCT0Phe6VSmOmMP46dFJYuAIoup6J/TsDLqGIG/G8bZPaAn1XtgjJ23Ptoielu1 +z7CcvO2Bxv5gDGUnd/oW+rWU1gJ2Aav62564Fy6tNSVnNWzWy3WGuqMjkzJsEy8L +3sklLhryd4vf1E2vvFRaupMUY9g0oVWB4wIBAg== +-----END DH PARAMETERS----- diff --git a/docker_test/dhparams_3072.pem b/docker_test/dhparams_3072.pem new file mode 100644 index 0000000..5a7c699 --- /dev/null +++ b/docker_test/dhparams_3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEAjoI7ICm70zsvw1DgmheGKxrpFz31cR2F+b4P5HwFPJ77EZDDNZQ2 +rmfJ6B1F4fFZZcGeEzuRvnujzy3grie33zRDvPLAFSzoTWjarh/bEiMcDFz/X2AY +7TAlC1snEmdcrnar8H7Twg2pWCbUKrwF/wsBsqjzXtokGqhseUTDgTUjP4JW94li +3SnqBPLGypFPGmwt5rq6IUARilOXHhwDfodV2JHvbdRvbIUivShYT9YpzLwA512s +sz4clyLNjFDpVdX9HtcQoJL7etStC8Jo7qJvpjkQUGxUrbZR7QM12YfHiT7+dOIi +PyLPGrEm11FWLntxyX+RuR8v5wVaXIiRziwRiz/xy4YM5giYXPQFSWNcSp7YlZO2 +8LyTreyWKp9hHPFN0B2PX1G5XU8bEsIeS/gUVorjd/k6/KsQGHhFpUTMAv43CgYI +UVXqw8DPGQKHejfmA5sX3rKTXZlxQjKofxsZUuymuH+Bn9tQKCLzFVWPMScM0Abb +xNG5W9qEvHGDAgEC +-----END DH PARAMETERS----- diff --git a/docker_test/dhparams_512.pem b/docker_test/dhparams_512.pem new file mode 100644 index 0000000..2ded3fb --- /dev/null +++ b/docker_test/dhparams_512.pem @@ -0,0 +1,4 @@ +-----BEGIN DH PARAMETERS----- +MEYCQQDGepU1BSbkViIkFsK+7q68p2ISObhxXRf9uZAqi1jfEhuFrE9IXrhs1CFe +QFW4cLx60bJttVU6acun8aaySWSjAgEC +-----END DH PARAMETERS----- diff --git a/docker_test/expected_output/test_1.txt b/docker_test/expected_output/test_1.txt new file mode 100644 index 0000000..f799dbf --- /dev/null +++ b/docker_test/expected_output/test_1.txt @@ -0,0 +1,125 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is enabled +TLSv1.0 is enabled +TLSv1.1 is enabled +TLSv1.2 is enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Secure session renegotiation supported + + TLS Compression: +Compression enabled (CRIME) + + Heartbleed: +TLS 1.2 not vulnerable to heartbleed +TLS 1.1 not vulnerable to heartbleed +TLS 1.0 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve P-256 DHE 256 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 2048 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 2048 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA384 Curve P-256 DHE 256 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 2048 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 2048 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 2048 bits +Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 2048 bits +Accepted TLSv1.2 128 bits DHE-RSA-SEED-SHA DHE 2048 bits +Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.2 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.2 112 bits DHE-RSA-DES-CBC3-SHA  DHE 2048 bits +Accepted TLSv1.2 256 bits AES256-GCM-SHA384 +Accepted TLSv1.2 128 bits AES128-GCM-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA256 +Accepted TLSv1.2 128 bits AES128-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA +Accepted TLSv1.2 256 bits CAMELLIA256-SHA +Accepted TLSv1.2 128 bits AES128-SHA +Accepted TLSv1.2 128 bits SEED-SHA +Accepted TLSv1.2 128 bits CAMELLIA128-SHA +Accepted TLSv1.2 128 bits RC4-SHA  +Accepted TLSv1.2 128 bits RC4-MD5  +Accepted TLSv1.2 112 bits DES-CBC3-SHA  +Preferred TLSv1.1 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 2048 bits +Accepted TLSv1.1 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits +Accepted TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 2048 bits +Accepted TLSv1.1 128 bits DHE-RSA-SEED-SHA DHE 2048 bits +Accepted TLSv1.1 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits +Accepted TLSv1.1 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.1 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.1 112 bits DHE-RSA-DES-CBC3-SHA  DHE 2048 bits +Accepted TLSv1.1 256 bits AES256-SHA +Accepted TLSv1.1 256 bits CAMELLIA256-SHA +Accepted TLSv1.1 128 bits AES128-SHA +Accepted TLSv1.1 128 bits SEED-SHA +Accepted TLSv1.1 128 bits CAMELLIA128-SHA +Accepted TLSv1.1 128 bits IDEA-CBC-SHA +Accepted TLSv1.1 128 bits RC4-SHA  +Accepted TLSv1.1 128 bits RC4-MD5  +Accepted TLSv1.1 112 bits DES-CBC3-SHA  +Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 2048 bits +Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 2048 bits +Accepted TLSv1.0 128 bits DHE-RSA-SEED-SHA DHE 2048 bits +Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 2048 bits +Accepted TLSv1.0 256 bits AES256-SHA +Accepted TLSv1.0 256 bits CAMELLIA256-SHA +Accepted TLSv1.0 128 bits AES128-SHA +Accepted TLSv1.0 128 bits SEED-SHA +Accepted TLSv1.0 128 bits CAMELLIA128-SHA +Accepted TLSv1.0 128 bits IDEA-CBC-SHA +Accepted TLSv1.0 128 bits RC4-SHA  +Accepted TLSv1.0 128 bits RC4-MD5  +Accepted TLSv1.0 112 bits DES-CBC3-SHA  + + Server Key Exchange Group(s): +TLSv1.2 128 bits secp256r1 (NIST P-256) + + Server Signature Algorithm(s): +TLSv1.2 rsa_pkcs1_sha1 +TLSv1.2 dsa_sha1 +TLSv1.2 ecdsa_sha1 +TLSv1.2 rsa_pkcs1_sha224 +TLSv1.2 dsa_sha224 +TLSv1.2 ecdsa_sha224 +TLSv1.2 rsa_pkcs1_sha256 +TLSv1.2 dsa_sha256 +TLSv1.2 ecdsa_secp256r1_sha256 +TLSv1.2 rsa_pkcs1_sha384 +TLSv1.2 dsa_sha384 +TLSv1.2 ecdsa_secp384r1_sha384 +TLSv1.2 rsa_pkcs1_sha512 +TLSv1.2 dsa_sha512 +TLSv1.2 ecdsa_secp521r1_sha512 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 2048 + +Subject: whythefuckwasibreached.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 03:01:23 2019 GMT +Not valid after: Dec 3 03:01:23 2029 GMT diff --git a/docker_test/expected_output/test_10.txt b/docker_test/expected_output/test_10.txt new file mode 100644 index 0000000..efa60e7 --- /dev/null +++ b/docker_test/expected_output/test_10.txt @@ -0,0 +1,24 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is enabled +TLSv1.3 is not enabled + + Supported Server Cipher(s): +Preferred 400 Bad Request TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve 25519 DHE 253 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 3072 + +Subject: lmgtfy.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 04:07:43 2019 GMT +Not valid after: Dec 3 04:07:43 2029 GMT diff --git a/docker_test/expected_output/test_11.txt b/docker_test/expected_output/test_11.txt new file mode 100644 index 0000000..f82112a --- /dev/null +++ b/docker_test/expected_output/test_11.txt @@ -0,0 +1,29 @@ + +Connected to + +Testing SSL server www.amazon.com on port 443 using SNI name www.amazon.com + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is enabled +TLSv1.1 is enabled +TLSv1.2 is enabled +TLSv1.3 is not enabled + + OCSP Stapling Request: +OCSP Response Status: successful (0x0) +Response Type: Basic OCSP Response +Version: 1 (0x0) +Responder Id: +Produced At: +Responses: + Certificate ID: + Hash Algorithm: + Issuer Name Hash: + Issuer Key Hash: + Serial Number: + Cert Status: good + This Update: + Next Update: + diff --git a/docker_test/expected_output/test_12.txt b/docker_test/expected_output/test_12.txt new file mode 100644 index 0000000..f606561 --- /dev/null +++ b/docker_test/expected_output/test_12.txt @@ -0,0 +1,62 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is enabled +SSLv3 is enabled +TLSv1.0 is enabled +TLSv1.1 is not enabled +TLSv1.2 is not enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Server does not support TLS Fallback SCSV + + TLS renegotiation: +Secure session renegotiation supported + + TLS Compression: +Compression enabled (CRIME) + + Heartbleed: +TLS 1.0 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 512 bits +Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 512 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 512 bits +Accepted TLSv1.0 128 bits DHE-RSA-SEED-SHA DHE 512 bits +Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 512 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 512 bits +Accepted TLSv1.0 256 bits AES256-SHA +Accepted TLSv1.0 256 bits CAMELLIA256-SHA +Accepted TLSv1.0 128 bits AES128-SHA +Accepted TLSv1.0 128 bits SEED-SHA +Accepted TLSv1.0 128 bits CAMELLIA128-SHA +Accepted TLSv1.0 128 bits IDEA-CBC-SHA +Accepted TLSv1.0 128 bits RC4-SHA  +Accepted TLSv1.0 128 bits RC4-MD5  +Accepted TLSv1.0 112 bits DES-CBC3-SHA  +Accepted TLSv1.0 56 bits TLS_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.0 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  + + Server Key Exchange Group(s): +TLSv1.0 128 bits secp256r1 (NIST P-256) + + Server Signature Algorithm(s): +TLSv1.0 Server accepts all signature algorithms. + + SSL Certificate: +Signature Algorithm: md5WithRSAEncryption +RSA Key Strength: 512 + +Subject: geocities.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 13 03:56:22 2019 GMT +Not valid after: Dec 13 03:56:22 2029 GMT diff --git a/docker_test/expected_output/test_13.txt b/docker_test/expected_output/test_13.txt new file mode 100644 index 0000000..ec94512 --- /dev/null +++ b/docker_test/expected_output/test_13.txt @@ -0,0 +1,93 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is enabled +TLSv1.1 is enabled +TLSv1.2 is enabled +TLSv1.3 is enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Secure session renegotiation supported + + TLS Compression: +Compression disabled + + Heartbleed: +TLS 1.3 not vulnerable to heartbleed +TLS 1.2 not vulnerable to heartbleed +TLS 1.1 not vulnerable to heartbleed +TLS 1.0 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256 Curve 25519 DHE 253 +Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384 Curve 25519 DHE 253 +Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256 Curve 25519 DHE 253 +Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve 25519 DHE 253 +Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 2048 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305  DHE 2048 bits +Accepted TLSv1.2 256 bits DHE-RSA-AES256-CCM DHE 2048 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 2048 bits +Accepted TLSv1.2 128 bits DHE-RSA-AES128-CCM DHE 2048 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 2048 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 2048 bits +Accepted TLSv1.2 256 bits AES256-GCM-SHA384 +Accepted TLSv1.2 256 bits AES256-CCM +Accepted TLSv1.2 128 bits AES128-GCM-SHA256 +Accepted TLSv1.2 128 bits AES128-CCM +Accepted TLSv1.2 256 bits AES256-SHA +Accepted TLSv1.2 128 bits AES128-SHA +Preferred TLSv1.1 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 2048 bits +Accepted TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 +Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 2048 bits +Accepted TLSv1.1 256 bits AES256-SHA +Accepted TLSv1.1 128 bits AES128-SHA +Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 2048 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 +Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 2048 bits +Accepted TLSv1.0 256 bits AES256-SHA +Accepted TLSv1.0 128 bits AES128-SHA + + Server Key Exchange Group(s): +TLSv1.3 128 bits secp256r1 (NIST P-256) +TLSv1.3 192 bits secp384r1 (NIST P-384) +TLSv1.3 260 bits secp521r1 (NIST P-521) +TLSv1.3 128 bits x25519 +TLSv1.3 112 bits ffdhe2048 +TLSv1.3 128 bits ffdhe3072 +TLSv1.3 150 bits ffdhe4096 +TLSv1.3 175 bits ffdhe6144 +TLSv1.3 192 bits ffdhe8192 +TLSv1.2 128 bits secp256r1 (NIST P-256) +TLSv1.2 192 bits secp384r1 (NIST P-384) +TLSv1.2 260 bits secp521r1 (NIST P-521) +TLSv1.2 128 bits x25519 + + Server Signature Algorithm(s): +TLSv1.3 rsa_pss_rsae_sha256 +TLSv1.3 rsa_pss_rsae_sha384 +TLSv1.3 rsa_pss_rsae_sha512 +TLSv1.2 Server accepts all signature algorithms. + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 3072 + +Subject: lmgtfy.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 04:07:43 2019 GMT +Not valid after: Dec 3 04:07:43 2029 GMT diff --git a/docker_test/expected_output/test_14.txt b/docker_test/expected_output/test_14.txt new file mode 100644 index 0000000..d31d47a --- /dev/null +++ b/docker_test/expected_output/test_14.txt @@ -0,0 +1,69 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is enabled +TLSv1.3 is enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Session renegotiation not supported + + TLS Compression: +Compression disabled + + Heartbleed: +TLS 1.3 not vulnerable to heartbleed +TLS 1.2 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256 Curve P-521 DHE 521 +Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384 Curve P-521 DHE 521 +Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256 Curve P-521 DHE 521 +Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve P-521 DHE 521 +Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve P-521 DHE 521 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 8192 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve P-521 DHE 521 +Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305  DHE 8192 bits +Accepted TLSv1.2 256 bits DHE-RSA-AES256-CCM DHE 8192 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve P-521 DHE 521 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 8192 bits +Accepted TLSv1.2 128 bits DHE-RSA-AES128-CCM DHE 8192 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve P-521 DHE 521 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 8192 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve P-521 DHE 521 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 8192 bits +Accepted TLSv1.2 256 bits AES256-GCM-SHA384 +Accepted TLSv1.2 256 bits AES256-CCM +Accepted TLSv1.2 128 bits AES128-GCM-SHA256 +Accepted TLSv1.2 128 bits AES128-CCM +Accepted TLSv1.2 256 bits AES256-SHA +Accepted TLSv1.2 128 bits AES128-SHA + + Server Key Exchange Group(s): +TLSv1.3 260 bits secp521r1 (NIST P-521) +TLSv1.3 192 bits ffdhe8192 +TLSv1.2 260 bits secp521r1 (NIST P-521) + + Server Signature Algorithm(s): +TLSv1.3 rsa_pss_rsae_sha256 +TLSv1.3 rsa_pss_rsae_sha384 +TLSv1.3 rsa_pss_rsae_sha512 +TLSv1.2 Server accepts all signature algorithms. + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 3072 + +Subject: lmgtfy.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 04:07:43 2019 GMT +Not valid after: Dec 3 04:07:43 2029 GMT diff --git a/docker_test/expected_output/test_15.txt b/docker_test/expected_output/test_15.txt new file mode 100644 index 0000000..afea69a --- /dev/null +++ b/docker_test/expected_output/test_15.txt @@ -0,0 +1,73 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is enabled +TLSv1.1 is enabled +TLSv1.2 is enabled +TLSv1.3 is enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Secure session renegotiation supported + + TLS Compression: +Compression disabled + + Heartbleed: +TLS 1.3 not vulnerable to heartbleed +TLS 1.2 not vulnerable to heartbleed +TLS 1.1 not vulnerable to heartbleed +TLS 1.0 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256 Curve 25519 DHE 253 +Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384 Curve 25519 DHE 253 +Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256 Curve 25519 DHE 253 +Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve 25519 DHE 253 +Preferred TLSv1.2 256 bits ECDHE-ECDSA-AES256-GCM-SHA384 Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits ECDHE-ECDSA-CHACHA20-POLY1305 Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits ECDHE-ECDSA-AES256-CCM Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-GCM-SHA256 Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-CCM Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits ECDHE-ECDSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-SHA Curve 25519 DHE 253 +Preferred TLSv1.1 256 bits ECDHE-ECDSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.1 128 bits ECDHE-ECDSA-AES128-SHA Curve 25519 DHE 253 +Preferred TLSv1.0 256 bits ECDHE-ECDSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.0 128 bits ECDHE-ECDSA-AES128-SHA Curve 25519 DHE 253 + + Server Key Exchange Group(s): +TLSv1.3 128 bits secp256r1 (NIST P-256) +TLSv1.3 192 bits secp384r1 (NIST P-384) +TLSv1.3 260 bits secp521r1 (NIST P-521) +TLSv1.3 128 bits x25519 +TLSv1.3 112 bits ffdhe2048 +TLSv1.3 128 bits ffdhe3072 +TLSv1.3 150 bits ffdhe4096 +TLSv1.3 175 bits ffdhe6144 +TLSv1.3 192 bits ffdhe8192 +TLSv1.2 128 bits secp256r1 (NIST P-256) +TLSv1.2 192 bits secp384r1 (NIST P-384) +TLSv1.2 260 bits secp521r1 (NIST P-521) +TLSv1.2 128 bits x25519 + + Server Signature Algorithm(s): +TLSv1.3 ecdsa_secp256r1_sha256 +TLSv1.2 ecdsa_sha1 +TLSv1.2 ecdsa_secp256r1_sha256 +TLSv1.2 ecdsa_secp384r1_sha384 +TLSv1.2 ecdsa_secp521r1_sha512 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +Subject: itspeanutbutterjellytime.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 22 19:01:56 2019 GMT +Not valid after: Dec 22 19:01:56 2029 GMT diff --git a/docker_test/expected_output/test_16.txt b/docker_test/expected_output/test_16.txt new file mode 100644 index 0000000..adb15b5 --- /dev/null +++ b/docker_test/expected_output/test_16.txt @@ -0,0 +1,77 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Session renegotiation not supported + + TLS Compression: +Compression disabled + + Heartbleed: +TLS 1.2 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 2048 bits +Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 2048 bits +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 2048 bits +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 2048 bits +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 2048 bits +Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 2048 bits +Accepted TLSv1.2 128 bits DHE-RSA-SEED-SHA DHE 2048 bits +Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits +Accepted TLSv1.2 112 bits DHE-RSA-DES-CBC3-SHA  DHE 2048 bits +Accepted TLSv1.2 256 bits AES256-GCM-SHA384 +Accepted TLSv1.2 128 bits AES128-GCM-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA256 +Accepted TLSv1.2 128 bits AES128-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA +Accepted TLSv1.2 256 bits CAMELLIA256-SHA +Accepted TLSv1.2 128 bits AES128-SHA +Accepted TLSv1.2 128 bits SEED-SHA +Accepted TLSv1.2 128 bits CAMELLIA128-SHA +Accepted TLSv1.2 128 bits RC4-SHA  +Accepted TLSv1.2 128 bits RC4-MD5  +Accepted TLSv1.2 112 bits DES-CBC3-SHA  + + Server Key Exchange Group(s): +TLSv1.2 81 bits sect163k1 + + Server Signature Algorithm(s): +TLSv1.2 rsa_pkcs1_sha1 +TLSv1.2 dsa_sha1 +TLSv1.2 ecdsa_sha1 +TLSv1.2 rsa_pkcs1_sha224 +TLSv1.2 dsa_sha224 +TLSv1.2 ecdsa_sha224 +TLSv1.2 rsa_pkcs1_sha256 +TLSv1.2 dsa_sha256 +TLSv1.2 ecdsa_secp256r1_sha256 +TLSv1.2 rsa_pkcs1_sha384 +TLSv1.2 dsa_sha384 +TLSv1.2 ecdsa_secp384r1_sha384 +TLSv1.2 rsa_pkcs1_sha512 +TLSv1.2 dsa_sha512 +TLSv1.2 ecdsa_secp521r1_sha512 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 1024 + +Subject: howfuckedismydatabase.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 03:56:52 2019 GMT +Not valid after: Dec 3 03:56:52 2029 GMT diff --git a/docker_test/expected_output/test_17.txt b/docker_test/expected_output/test_17.txt new file mode 100644 index 0000000..c8229b7 --- /dev/null +++ b/docker_test/expected_output/test_17.txt @@ -0,0 +1,60 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Session renegotiation not supported + + TLS Compression: +Compression disabled + + Heartbleed: +TLS 1.2 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 1024 bits +Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305  DHE 1024 bits +Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 1024 bits +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 1024 bits +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 1024 bits +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 1024 bits +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 1024 bits +Accepted TLSv1.2 256 bits AES256-GCM-SHA384 +Accepted TLSv1.2 128 bits AES128-GCM-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA256 +Accepted TLSv1.2 128 bits AES128-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA +Accepted TLSv1.2 128 bits AES128-SHA + + Server Key Exchange Group(s): +TLSv1.2 256 bits brainpoolP512r1 + + Server Signature Algorithm(s): +TLSv1.2 rsa_pkcs1_sha1 +TLSv1.2 rsa_pkcs1_sha224 +TLSv1.2 rsa_pkcs1_sha256 +TLSv1.2 rsa_pkcs1_sha384 +TLSv1.2 rsa_pkcs1_sha512 +TLSv1.2 rsa_pss_rsae_sha256 +TLSv1.2 rsa_pss_rsae_sha384 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 1024 + +Subject: howfuckedismydatabase.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 03:56:52 2019 GMT +Not valid after: Dec 3 03:56:52 2029 GMT diff --git a/docker_test/expected_output/test_18.txt b/docker_test/expected_output/test_18.txt new file mode 100644 index 0000000..2eb2b0b --- /dev/null +++ b/docker_test/expected_output/test_18.txt @@ -0,0 +1,45 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Session renegotiation not supported + + TLS Compression: +Compression disabled + + Heartbleed: +TLS 1.2 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.2 256 bits ECDHE-ECDSA-CHACHA20-POLY1305 Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-GCM-SHA256 Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + + Server Key Exchange Group(s): +TLSv1.2 128 bits secp256r1 (NIST P-256) +TLSv1.2 192 bits secp384r1 (NIST P-384) +TLSv1.2 260 bits secp521r1 (NIST P-521) +TLSv1.2 128 bits x25519 + + Server Signature Algorithm(s): +TLSv1.2 ecdsa_sha1 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +Subject: itspeanutbutterjellytime.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 22 19:01:56 2019 GMT +Not valid after: Dec 22 19:01:56 2029 GMT diff --git a/docker_test/expected_output/test_2.txt b/docker_test/expected_output/test_2.txt new file mode 100644 index 0000000..2436c45 --- /dev/null +++ b/docker_test/expected_output/test_2.txt @@ -0,0 +1,27 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is enabled +SSLv3 is not enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is not enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Connection failed - unable to determine TLS Fallback SCSV support + + TLS renegotiation: +Session renegotiation not supported + + TLS Compression: +Compression disabled + + Heartbleed: + + Supported Server Cipher(s): +Certificate information cannot be enumerated through SSLv2 nor SSLv3. + diff --git a/docker_test/expected_output/test_3.txt b/docker_test/expected_output/test_3.txt new file mode 100644 index 0000000..8566e7e --- /dev/null +++ b/docker_test/expected_output/test_3.txt @@ -0,0 +1,27 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is not enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Connection failed - unable to determine TLS Fallback SCSV support + + TLS renegotiation: +Session renegotiation not supported + + TLS Compression: +Compression disabled + + Heartbleed: + + Supported Server Cipher(s): +Certificate information cannot be enumerated through SSLv2 nor SSLv3. + diff --git a/docker_test/expected_output/test_4.txt b/docker_test/expected_output/test_4.txt new file mode 100644 index 0000000..d68fed9 --- /dev/null +++ b/docker_test/expected_output/test_4.txt @@ -0,0 +1,98 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is enabled +TLSv1.1 is enabled +TLSv1.2 is enabled +TLSv1.3 is enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Secure session renegotiation supported + + TLS Compression: +Compression disabled + + Heartbleed: +TLS 1.3 not vulnerable to heartbleed +TLS 1.2 not vulnerable to heartbleed +TLS 1.1 not vulnerable to heartbleed +TLS 1.0 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256 Curve 25519 DHE 253 +Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384 Curve 25519 DHE 253 +Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256 Curve 25519 DHE 253 +Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 3072 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305  DHE 3072 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 3072 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA384 Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 3072 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 3072 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 3072 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 3072 bits +Accepted TLSv1.2 256 bits AES256-GCM-SHA384 +Accepted TLSv1.2 128 bits AES128-GCM-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA256 +Accepted TLSv1.2 128 bits AES128-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA +Accepted TLSv1.2 128 bits AES128-SHA +Preferred TLSv1.1 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 3072 bits +Accepted TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 +Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 3072 bits +Accepted TLSv1.1 256 bits AES256-SHA +Accepted TLSv1.1 128 bits AES128-SHA +Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 +Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 3072 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 +Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 3072 bits +Accepted TLSv1.0 256 bits AES256-SHA +Accepted TLSv1.0 128 bits AES128-SHA + + Server Key Exchange Group(s): +TLSv1.3 128 bits secp256r1 (NIST P-256) +TLSv1.3 192 bits secp384r1 (NIST P-384) +TLSv1.3 260 bits secp521r1 (NIST P-521) +TLSv1.3 128 bits x25519 +TLSv1.3 224 bits x448 +TLSv1.2 128 bits secp256r1 (NIST P-256) +TLSv1.2 192 bits secp384r1 (NIST P-384) +TLSv1.2 260 bits secp521r1 (NIST P-521) +TLSv1.2 128 bits x25519 +TLSv1.2 224 bits x448 + + Server Signature Algorithm(s): +TLSv1.3 rsa_pss_rsae_sha256 +TLSv1.3 rsa_pss_rsae_sha384 +TLSv1.3 rsa_pss_rsae_sha512 +TLSv1.2 rsa_pkcs1_sha1 +TLSv1.2 rsa_pkcs1_sha224 +TLSv1.2 rsa_pkcs1_sha256 +TLSv1.2 rsa_pkcs1_sha384 +TLSv1.2 rsa_pkcs1_sha512 +TLSv1.2 rsa_pss_rsae_sha256 +TLSv1.2 rsa_pss_rsae_sha384 +TLSv1.2 rsa_pss_rsae_sha512 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 3072 + +Subject: lmgtfy.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 04:07:43 2019 GMT +Not valid after: Dec 3 04:07:43 2029 GMT diff --git a/docker_test/expected_output/test_5.txt b/docker_test/expected_output/test_5.txt new file mode 100644 index 0000000..b1dcea0 --- /dev/null +++ b/docker_test/expected_output/test_5.txt @@ -0,0 +1,180 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is enabled +TLSv1.0 is enabled +TLSv1.1 is enabled +TLSv1.2 is enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Secure session renegotiation supported + + TLS Compression: +Compression enabled (CRIME) + + Heartbleed: +TLS 1.2 not vulnerable to heartbleed +TLS 1.1 not vulnerable to heartbleed +TLS 1.0 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve P-256 DHE 256 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 1024 bits +Accepted TLSv1.2 256 bits ADH-AES256-GCM-SHA384  DHE 1024 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 1024 bits +Accepted TLSv1.2 128 bits ADH-AES128-GCM-SHA256  DHE 1024 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA384 Curve P-256 DHE 256 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 1024 bits +Accepted TLSv1.2 256 bits ADH-AES256-SHA256  DHE 1024 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 1024 bits +Accepted TLSv1.2 128 bits ADH-AES128-SHA256  DHE 1024 bits +Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 1024 bits +Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 1024 bits +Accepted TLSv1.2 256 bits AECDH-AES256-SHA  Curve P-256 DHE 256 +Accepted TLSv1.2 256 bits ADH-AES256-SHA  DHE 1024 bits +Accepted TLSv1.2 256 bits ADH-CAMELLIA256-SHA  DHE 1024 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 1024 bits +Accepted TLSv1.2 128 bits DHE-RSA-SEED-SHA DHE 1024 bits +Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 1024 bits +Accepted TLSv1.2 128 bits AECDH-AES128-SHA  Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits ADH-AES128-SHA  DHE 1024 bits +Accepted TLSv1.2 128 bits ADH-SEED-SHA  DHE 1024 bits +Accepted TLSv1.2 128 bits ADH-CAMELLIA128-SHA  DHE 1024 bits +Accepted TLSv1.2 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits AECDH-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.2 128 bits ADH-RC4-MD5  DHE 1024 bits +Accepted TLSv1.2 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.2 112 bits DHE-RSA-DES-CBC3-SHA  DHE 1024 bits +Accepted TLSv1.2 112 bits AECDH-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.2 112 bits ADH-DES-CBC3-SHA  DHE 1024 bits +Accepted TLSv1.2 256 bits AES256-GCM-SHA384 +Accepted TLSv1.2 128 bits AES128-GCM-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA256 +Accepted TLSv1.2 128 bits AES128-SHA256 +Accepted TLSv1.2 256 bits AES256-SHA +Accepted TLSv1.2 256 bits CAMELLIA256-SHA +Accepted TLSv1.2 128 bits AES128-SHA +Accepted TLSv1.2 128 bits SEED-SHA +Accepted TLSv1.2 128 bits CAMELLIA128-SHA +Accepted TLSv1.2 128 bits RC4-SHA  +Accepted TLSv1.2 128 bits RC4-MD5  +Accepted TLSv1.2 112 bits DES-CBC3-SHA  +Accepted TLSv1.2 40 bits TLS_RSA_EXPORT_WITH_RC4_40_MD5 +Accepted TLSv1.2 40 bits TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 +Accepted TLSv1.2 40 bits TLS_RSA_EXPORT_WITH_DES40_CBC_SHA +Accepted TLSv1.2 56 bits TLS_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.2 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.2 56 bits TLS_DH_anon_WITH_DES_CBC_SHA  +Preferred TLSv1.1 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 1024 bits +Accepted TLSv1.1 256 bits DHE-RSA-CAMELLIA256-SHA DHE 1024 bits +Accepted TLSv1.1 256 bits AECDH-AES256-SHA  Curve P-256 DHE 256 +Accepted TLSv1.1 256 bits ADH-AES256-SHA  DHE 1024 bits +Accepted TLSv1.1 256 bits ADH-CAMELLIA256-SHA  DHE 1024 bits +Accepted TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 1024 bits +Accepted TLSv1.1 128 bits DHE-RSA-SEED-SHA DHE 1024 bits +Accepted TLSv1.1 128 bits DHE-RSA-CAMELLIA128-SHA DHE 1024 bits +Accepted TLSv1.1 128 bits AECDH-AES128-SHA  Curve P-256 DHE 256 +Accepted TLSv1.1 128 bits ADH-AES128-SHA  DHE 1024 bits +Accepted TLSv1.1 128 bits ADH-SEED-SHA  DHE 1024 bits +Accepted TLSv1.1 128 bits ADH-CAMELLIA128-SHA  DHE 1024 bits +Accepted TLSv1.1 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.1 128 bits AECDH-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.1 128 bits ADH-RC4-MD5  DHE 1024 bits +Accepted TLSv1.1 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.1 112 bits DHE-RSA-DES-CBC3-SHA  DHE 1024 bits +Accepted TLSv1.1 112 bits AECDH-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.1 112 bits ADH-DES-CBC3-SHA  DHE 1024 bits +Accepted TLSv1.1 256 bits AES256-SHA +Accepted TLSv1.1 256 bits CAMELLIA256-SHA +Accepted TLSv1.1 128 bits AES128-SHA +Accepted TLSv1.1 128 bits SEED-SHA +Accepted TLSv1.1 128 bits CAMELLIA128-SHA +Accepted TLSv1.1 128 bits IDEA-CBC-SHA +Accepted TLSv1.1 128 bits RC4-SHA  +Accepted TLSv1.1 128 bits RC4-MD5  +Accepted TLSv1.1 112 bits DES-CBC3-SHA  +Accepted TLSv1.1 40 bits TLS_RSA_EXPORT_WITH_RC4_40_MD5 +Accepted TLSv1.1 40 bits TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 +Accepted TLSv1.1 40 bits TLS_RSA_EXPORT_WITH_DES40_CBC_SHA +Accepted TLSv1.1 56 bits TLS_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.1 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.1 56 bits TLS_DH_anon_WITH_DES_CBC_SHA  +Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 1024 bits +Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 1024 bits +Accepted TLSv1.0 256 bits AECDH-AES256-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 256 bits ADH-AES256-SHA  DHE 1024 bits +Accepted TLSv1.0 256 bits ADH-CAMELLIA256-SHA  DHE 1024 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 1024 bits +Accepted TLSv1.0 128 bits DHE-RSA-SEED-SHA DHE 1024 bits +Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 1024 bits +Accepted TLSv1.0 128 bits AECDH-AES128-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits ADH-AES128-SHA  DHE 1024 bits +Accepted TLSv1.0 128 bits ADH-SEED-SHA  DHE 1024 bits +Accepted TLSv1.0 128 bits ADH-CAMELLIA128-SHA  DHE 1024 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits AECDH-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits ADH-RC4-MD5  DHE 1024 bits +Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 1024 bits +Accepted TLSv1.0 112 bits AECDH-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits ADH-DES-CBC3-SHA  DHE 1024 bits +Accepted TLSv1.0 256 bits AES256-SHA +Accepted TLSv1.0 256 bits CAMELLIA256-SHA +Accepted TLSv1.0 128 bits AES128-SHA +Accepted TLSv1.0 128 bits SEED-SHA +Accepted TLSv1.0 128 bits CAMELLIA128-SHA +Accepted TLSv1.0 128 bits IDEA-CBC-SHA +Accepted TLSv1.0 128 bits RC4-SHA  +Accepted TLSv1.0 128 bits RC4-MD5  +Accepted TLSv1.0 112 bits DES-CBC3-SHA  +Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_RC4_40_MD5 +Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 +Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_DES40_CBC_SHA +Accepted TLSv1.0 56 bits TLS_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.0 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.0 56 bits TLS_DH_anon_WITH_DES_CBC_SHA  + + Server Key Exchange Group(s): +TLSv1.2 128 bits secp256r1 (NIST P-256) + + Server Signature Algorithm(s): +TLSv1.2 rsa_pkcs1_sha1 +TLSv1.2 dsa_sha1 +TLSv1.2 ecdsa_sha1 +TLSv1.2 rsa_pkcs1_sha224 +TLSv1.2 dsa_sha224 +TLSv1.2 ecdsa_sha224 +TLSv1.2 rsa_pkcs1_sha256 +TLSv1.2 dsa_sha256 +TLSv1.2 ecdsa_secp256r1_sha256 +TLSv1.2 rsa_pkcs1_sha384 +TLSv1.2 dsa_sha384 +TLSv1.2 ecdsa_secp384r1_sha384 +TLSv1.2 rsa_pkcs1_sha512 +TLSv1.2 dsa_sha512 +TLSv1.2 ecdsa_secp521r1_sha512 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 1024 + +Subject: howfuckedismydatabase.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 03:56:52 2019 GMT +Not valid after: Dec 3 03:56:52 2029 GMT diff --git a/docker_test/expected_output/test_6.txt b/docker_test/expected_output/test_6.txt new file mode 100644 index 0000000..b6bf355 --- /dev/null +++ b/docker_test/expected_output/test_6.txt @@ -0,0 +1,52 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is not enabled +TLSv1.3 is enabled + + TLS Fallback SCSV: +Server supports TLS Fallback SCSV + + TLS renegotiation: +Session renegotiation not supported + + TLS Compression: +Compression disabled + + Heartbleed: +TLS 1.3 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256 Curve 25519 DHE 253 +Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384 Curve 25519 DHE 253 +Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256 Curve 25519 DHE 253 +Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve 25519 DHE 253 +Accepted TLSv1.3 128 bits TLS_AES_128_CCM_8_SHA256 Curve 25519 DHE 253 + + Server Key Exchange Group(s): +TLSv1.3 128 bits secp256r1 (NIST P-256) +TLSv1.3 192 bits secp384r1 (NIST P-384) +TLSv1.3 260 bits secp521r1 (NIST P-521) +TLSv1.3 128 bits x25519 +TLSv1.3 224 bits x448 + + Server Signature Algorithm(s): +TLSv1.3 rsa_pss_rsae_sha256 +TLSv1.3 rsa_pss_rsae_sha384 +TLSv1.3 rsa_pss_rsae_sha512 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 3072 + +Subject: lmgtfy.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 04:07:43 2019 GMT +Not valid after: Dec 3 04:07:43 2029 GMT diff --git a/docker_test/expected_output/test_7.txt b/docker_test/expected_output/test_7.txt new file mode 100644 index 0000000..de5de11 --- /dev/null +++ b/docker_test/expected_output/test_7.txt @@ -0,0 +1,62 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is enabled +SSLv3 is enabled +TLSv1.0 is enabled +TLSv1.1 is not enabled +TLSv1.2 is not enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Server does not support TLS Fallback SCSV + + TLS renegotiation: +Secure session renegotiation supported + + TLS Compression: +Compression enabled (CRIME) + + Heartbleed: +TLS 1.0 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 512 bits +Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 512 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 512 bits +Accepted TLSv1.0 128 bits DHE-RSA-SEED-SHA DHE 512 bits +Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 512 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 512 bits +Accepted TLSv1.0 256 bits AES256-SHA +Accepted TLSv1.0 256 bits CAMELLIA256-SHA +Accepted TLSv1.0 128 bits AES128-SHA +Accepted TLSv1.0 128 bits SEED-SHA +Accepted TLSv1.0 128 bits CAMELLIA128-SHA +Accepted TLSv1.0 128 bits IDEA-CBC-SHA +Accepted TLSv1.0 128 bits RC4-SHA  +Accepted TLSv1.0 128 bits RC4-MD5  +Accepted TLSv1.0 112 bits DES-CBC3-SHA  +Accepted TLSv1.0 56 bits TLS_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.0 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  + + Server Key Exchange Group(s): +TLSv1.0 128 bits secp256r1 (NIST P-256) + + Server Signature Algorithm(s): +TLSv1.0 Server accepts all signature algorithms. + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 3072 + +Subject: lmgtfy.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 04:07:43 2019 GMT +Not valid after: Dec 3 04:07:43 2029 GMT diff --git a/docker_test/expected_output/test_8.txt b/docker_test/expected_output/test_8.txt new file mode 100644 index 0000000..82aacab --- /dev/null +++ b/docker_test/expected_output/test_8.txt @@ -0,0 +1,84 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is enabled +SSLv3 is enabled +TLSv1.0 is enabled +TLSv1.1 is not enabled +TLSv1.2 is not enabled +TLSv1.3 is not enabled + + TLS Fallback SCSV: +Server does not support TLS Fallback SCSV + + TLS renegotiation: +Secure session renegotiation supported + + TLS Compression: +Compression enabled (CRIME) + + Heartbleed: +TLS 1.0 not vulnerable to heartbleed + + Supported Server Cipher(s): +Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 512 bits +Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 512 bits +Accepted TLSv1.0 256 bits AECDH-AES256-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 256 bits ADH-AES256-SHA  DHE 512 bits +Accepted TLSv1.0 256 bits ADH-CAMELLIA256-SHA  DHE 512 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 512 bits +Accepted TLSv1.0 128 bits DHE-RSA-SEED-SHA DHE 512 bits +Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 512 bits +Accepted TLSv1.0 128 bits AECDH-AES128-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits ADH-AES128-SHA  DHE 512 bits +Accepted TLSv1.0 128 bits ADH-SEED-SHA  DHE 512 bits +Accepted TLSv1.0 128 bits ADH-CAMELLIA128-SHA  DHE 512 bits +Accepted TLSv1.0 128 bits ECDHE-RSA-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits AECDH-RC4-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 128 bits ADH-RC4-MD5  DHE 512 bits +Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 512 bits +Accepted TLSv1.0 112 bits AECDH-DES-CBC3-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 112 bits ADH-DES-CBC3-SHA  DHE 512 bits +Accepted TLSv1.0 256 bits AES256-SHA +Accepted TLSv1.0 256 bits CAMELLIA256-SHA +Accepted TLSv1.0 128 bits AES128-SHA +Accepted TLSv1.0 128 bits SEED-SHA +Accepted TLSv1.0 128 bits CAMELLIA128-SHA +Accepted TLSv1.0 128 bits IDEA-CBC-SHA +Accepted TLSv1.0 128 bits RC4-SHA  +Accepted TLSv1.0 128 bits RC4-MD5  +Accepted TLSv1.0 112 bits DES-CBC3-SHA  +Accepted TLSv1.0 0 bits ECDHE-RSA-NULL-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 0 bits AECDH-NULL-SHA  Curve P-256 DHE 256 +Accepted TLSv1.0 0 bits NULL-SHA  +Accepted TLSv1.0 0 bits NULL-MD5  +Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_RC4_40_MD5 +Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 +Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_DES40_CBC_SHA +Accepted TLSv1.0 56 bits TLS_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.0 40 bits TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA +Accepted TLSv1.0 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  +Accepted TLSv1.0 40 bits TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 +Accepted TLSv1.0 40 bits TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA +Accepted TLSv1.0 56 bits TLS_DH_anon_WITH_DES_CBC_SHA  + + Server Key Exchange Group(s): +TLSv1.0 128 bits secp256r1 (NIST P-256) + + Server Signature Algorithm(s): +TLSv1.0 Server accepts all signature algorithms. + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 3072 + +Subject: lmgtfy.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 04:07:43 2019 GMT +Not valid after: Dec 3 04:07:43 2029 GMT diff --git a/docker_test/expected_output/test_9.txt b/docker_test/expected_output/test_9.txt new file mode 100644 index 0000000..69d540e --- /dev/null +++ b/docker_test/expected_output/test_9.txt @@ -0,0 +1,24 @@ + +Connected to 127.0.0.1 + +Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 + + SSL/TLS Protocols: +SSLv2 is not enabled +SSLv3 is not enabled +TLSv1.0 is not enabled +TLSv1.1 is not enabled +TLSv1.2 is enabled +TLSv1.3 is not enabled + + Supported Server Cipher(s): +Preferred 200 OK TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve 25519 DHE 253 + + SSL Certificate: +Signature Algorithm: sha256WithRSAEncryption +RSA Key Strength: 3072 + +Subject: lmgtfy.com +Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere +Not valid before: Dec 3 04:07:43 2019 GMT +Not valid after: Dec 3 04:07:43 2029 GMT diff --git a/docker_test/key_1024.pem b/docker_test/key_1024.pem new file mode 100644 index 0000000..8621f9c --- /dev/null +++ b/docker_test/key_1024.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDmpPrmBNS3gqCgCB9lKvH4ZpX9FvHzw3P4kNbyN45+8yq7gBUp +f9JYFQO0rqm0hSebJSQUDkhrFfO6onZdsMyN32lPlVPFmBILMBPgaxJTVUOa+TWx +gyVuPgaftrMQMr0Wvhbv+3Xht5hqPTEKe/GEwxXJKPSm2F1AgAkkwlQRzQIDAQAB +AoGBAJgeR7xdg05lQTtLICnBYUXLozEBaSK0zlAqdxnZuonQJ2by2wI746dkdMU+ +TX9aMv0ISftQUEMQf2egryCr8rx+yq8bI7LVF8H210x+8BT0H+gmd0iIcFNJNL0l +WSSIAmRVTbSK0IwsvEDwR+Egcnd8wA/9s/s9d2GmbChjisIBAkEA/QY1YLKkG+IT +Ad7GaOKv/UFQNLu7yLDtfjJcJ+dpjCWPv1B/orh6dwFJ4F+7MYruu0BAXhnvw70s +uyPH9W290QJBAOlbZEZtl5n5iL+czI0Ibkyn9VlZ44kgVQHs9Y5hFG0Hv1VH66EP +hU7ZeUUfSmiPqnTcVEKQFZjl09FSoVzTJz0CQQDROzsUlWTjsdUp7MCBp0ME1+et +U7j7QmOBwb83OEOtorn16GlDc+3BTw16P2+ajlrP+VfA+Q2t/VdqATKvH2qhAkBk +zLJ67Zn/y9czFbMR9KNYf3CuwPJVaF7v7wB/GRYuppsSZne04bRuw+frYMHOeshh +pE7NVdnOavBdSfkj1J3tAkEAjQ/+3cGCBiv9lnDdlszKW/Zq4Uu19znfQSbSbI8L +JezLQJbSlVDPG3W3NSNkLizrOg1H6AG2pnnVq2q++Lt5tQ== +-----END RSA PRIVATE KEY----- diff --git a/docker_test/key_2048.pem b/docker_test/key_2048.pem new file mode 100644 index 0000000..f9b36c9 --- /dev/null +++ b/docker_test/key_2048.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAywGmJp/AoA4TCs6zbXuiBOkho35IeVvpsy7RqM3y3KxkEFnk +/LM6U/ayL+j2vo4/15WPM0PaAGRRbvnQEuI1xvhn/0/T4xP+TBe91pTMo/nKrK/y +cvBLBqLPZQK9SJbHk6mwfgpQs5S/+VHlU9jl7+eQWcR+o3NXtv4XFlQyqx1dcokA +JrL4wr2vGPkigUNU2iI6FwRB4f7Wo1rBNzI49uE97IWuh+VBMPYMp+Zn2Om4ptCy +jdvSI7DEYc6jyKlPzH2UOgd0RkcwivaSpxfXJEBOC8PtOxyLg/KPjUTwUh0nHSpe +OIbT3HKnOErEbbiHQmlYbbcOyinv3hIlRj+PyQIDAQABAoIBAGiA09BkQpviQuk4 +WOOOVmxiut9YHeTjbN3Bx0o3osL4t5Y3QIrZlLgucbH6IjMcNT88jXgdgLbc7ZLM +ZNGjw31G2Pp0VKY735e6TQ6OkP4Ek9HrzUpf6q9i1pKwI1Kf0+Nu4h0wIDUh6OVm +xEAyksO6F/QuE+b+dHQOP0JOW7r7uxTMB/tbs1U+idcIRVrPTlO9Ixuaolmd/flz +jmcwwTtwBe+mA53IywCOV6ZxO3lMKzDkSvViRam37fmSh9JJyPEa6KpPTR5ps3w8 +7eG0u9nsEf1wYVA2u575iH4+uM6250bRuw3icZxTU2FPuMOtzJPnxY+A6q13bteW +h0zdzbUCgYEA6ryUy+BSOIFzX4e6dB2gwmn2PUEF1rO9dOG8H0YktOGHnHFDXECy +FYHf6njWEzwztd9ZiE8YQYjAjn829Gr4e45H6rEPAMzSpOJ/ZoLd6PG8d5L6A7AD +RtMS8KzG2fAMwvd0HJ0N4SwuwhFmq6/TLHB9vstwo0myyYqH2qWIOAcCgYEA3WVC +2VnrcuMZngYpXP+gWQDhkIxI7yqUhTB+OZGxHMMjfJ72JHKOI3StnQWSqhxmFtWF +x+XtnihcaWG+G7Po6TmW75oazoitqXjiixJOXGrN3jcmFj97nIh3NlhG2mskP9Ut +5iDE2w2nDRk1eI+13c7j12/bJy7kdi70gr0l5a8CgYEA03V6nYbAysJiyqYco0ml +bj3CYz/WIKnefBJ2Q74Ohxu77IRj6BEn3BQZQMIGJ2HOO4KuxwppkW+99yBGwzwy +CCwOQS+rkk7xWzPnDNPLUHOkEhvHOdcvvHec0k7y+5UyCdidMsGQpU4F+TFvyi4k +EB5uSJhAKfjUJJa095Sy97UCgYEAlOLpPtP6w+s3qg7IuFLsWY5/Ir9EuRowgRVo +fXyd2BLfBYq9SyuCrRNlQeiihiXM/eQgMJtO3gKUiwYBXA30PwvMlltTVbuS1hqG +dzIbYoks4xjBU0rj7RPU38Yj9/T/jrHlSRKWcB3RTry6OdajXoQosxP1FHezikrv +ghCDsN8CgYEA4JuCSuOxmP5/4MTl9oLUDHDbUBGPZICR+2Y0I76kRISQbHT+oidz +/ceQpOP20fBQquVhMrHmKthyN13TvBSn5SaNIa5SVIIGhVZJQPU1/Udfox1gx7iF +TcFx7dbMIh7byuVRy8iIyaVYr9ZtSX+6mYWFUXVrzF9LTGyDVta6YQA= +-----END RSA PRIVATE KEY----- diff --git a/docker_test/key_3072.pem b/docker_test/key_3072.pem new file mode 100644 index 0000000..7e36eb7 --- /dev/null +++ b/docker_test/key_3072.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAxA1ToQ2HLVYDmKSjPSlCposbUMYA30BlRXMzdJe1OVBg/qwE +rhURlFAvGF9ljgXFnMZ6oTK164sJXscjNXS/AbqWO9rBeMbUxD85/PRo4emmBVio +e5A/A4xbAvPt1snwgjbtZNTsxZoheUox216/NTJ24c3SGEBOlASBHtT6VBJPamx1 +aALlSlS4jqtLAlkxz6M/XUPeRER6DKYXUi37w0XCZRRk1U2ueM2nfkz47a/GxoeA +WmvWPVW1Bu+VbJb9Hsh/2otyhHZAVX9/fsKZwHf9qcSrutLk5M0ix9NUFnq8qZVu +ZLTZa7/rCw6YnmlOv1mAZJ8sNJtt1wyhMGLebkfVHKERCqk37LRpSzloTu95+uPu +/q+391XMKTOmMHqwhvZBpAoOvN7bs4o8N1JF8hPu+MBGsZUs8P+e9WTJU29zvORW +d7Z/8K1zakihJD9FXcC38OGO88h/7JVxYcMyVUZW3zZKxITlJWl8J18OqQpT66K4 +ceLOW1SjRIeHGX9TAgMBAAECggF/D1D7N5nW9bPClCpIln6itmAnwie16bseLk7R +tkoj3lZpPXwy4WbD+NJK25yYUoAg8B6RdgaAL+as1Lq6BXMZeQkas5Jjiwv9k1dd +MGXny751OfWzM/QQ+DX+5jwoWJ9uKr4fzcDUvptMAi3Jt1mvlnha0UlDIKHlgarY +a5A3/llv2uCeS4HuZ+A2iu7W7VgKjC40xRSISM0Qu+w95i2xfY/1n+/38LIg708h +xrw8tlUFMn1jiazjD+eiPOh6xAEHojAGu1actfW+jg8NySpTGWAUPfTxXV9J6r/c +BdCldXP5lQHfWKBIAKUK9MZyrFFQnZZMdPDXyyKsfbO04gVW5BsEK9Br5dnGbFGu +e+Ve4jOCAC9//wLqgLDL2t3CCnnPU1bGFnqLqzwtEKrEP3XeK1CFLYCwOZ2tUH9h +IbQRZKbEMlsXR4XvplmwjNqRb/uHSIVmPJ1DVXbFZy/2j7i59+Kl+JqINHEPvGc1 +tfLOFvOHYRWRONkylj3O+qH6lyECgcEA+CErcMNYkM7Y2uRRB2UhQQ96NDoflQmg +uObO0XTnhMbRFrRRrgEr0POOo4oCqDSVQk/vJjmB1ugo/IKxGphnAOmi1xDpSXqo +UWnUR34nrqL76ZdV1R3FZX0b4iO9X1R/P9sNl4S0+XCDyAMlcaXroPoUIo9mzxbX +vIAk6lMiJijfzLt7RssVCfgCfHZ9srBMG5oaEfTbFImc9fwjNoJdLTDopEQzA1X5 +AjVa8VhIGyE+uoLkPsy9jBNF9asEEdc/AoHBAMpFSKUdTIXuYOOGltr1qFAMofUU ++ztagHg1/UdV3EOhkYZOfpa4clu++x0MNp+bRySxEK6IOpEtSaKHaJlHnvR4+4e7 +xQp/jBoWCrxWtqXHe3ufyglsq/1ID7HIEGfBs9IAVPx9PkY9IOC8cXX3q9uRB7xM +MCtl/H8QMf01f4p3vEgx+XXb2+MKsjOqOVDpAqfqrcUmTiK9ixC7BJWwWSBAvN4e +2jS4UEOoBiczX6qhKo+tUEddfnAJGnxp2cZG7QKBwHwU8klIltCLb+w+grrE+tUz +LTRS4JpCH0p3uXMLF//RAJxu/e2bDlNGiM0FZgDBkuZ/XKNr3J8gp+ZmYLRhBBlz +vIf6H/8rxGI6HvrFfoiZXopYsIaLhbwTzU7P+pJiiePf4jMkHPAkMPJjiGUFyQhO +JqWFuq7SyH2uQ0ee3RPiGtCh7KrhQZsjl/KvunoSKW0gKetS2/+wNXrZZK6MkJXZ +wGzs4enII2bUUa8hK6XNgTX54LP65MrYlIKey8E0NwKBwHBb3kfCJ8D6Mx4QpHoL +Hi0hZ1ISDqDg3B5qt0BKJKn49TKrJcyptvTZ+Pogz7MHeZSbO04IZKhChPXgzCzh +SR46mlbC6mizg2r2NY57iMg8MI7yqzNjB4MR5Y33OY25Xx9Xid4b4Fz6FephI5HJ +O9EjFi32EIf7BjC7GVmzvx529sMP56gdsl7DkUv70gzs8sm+Jjsu1RadPcPUb26L +YGb3LzMf5kyE2ilLC+f4tLq+/jqDpuWNvO+VTv4veoaW3QKBwQDQlmXDJ+4SdYnD +QkHis9G5AnyXkUHhBFTWLyhsJMrt3CZyVp8L7xXgEJTsSVoyvURimeBmua4LEqci +5PPo1fOfyEqUIrHIJVR26ATeMsxC3icV6kna7cD0K1BILtAGTJeO7sWceFhl2QJb +E4wio0Vljyt+foytCL/KV3bIj/OYGk8bUp1OMzEIXot4kx3l2SOf+cYE5UDca9Ey +Z/6IvSvAP/JSqo2pk4azaqxSuZIMQnZB2YlFxllCZ6ce/Z6YcSs= +-----END RSA PRIVATE KEY----- diff --git a/docker_test/key_512.pem b/docker_test/key_512.pem new file mode 100644 index 0000000..4237078 --- /dev/null +++ b/docker_test/key_512.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBPQIBAAJBAMvdzx+XSLVGpLLVy0NIBZVs6k7Lxviu5Cym+5n0zbwsYKtiralI +vc0HPekJik1o/QLgqcO83837wOS8hPU0k9UCAwEAAQJBAJP8Vj7TXZchSar7oMod +PNhkMI20RKH+qmlzaU4vsyx1Kqcv2uTkAPMugNZZtRP7bOYU9inbH8LUIrHJIpZP +/H0CIQDliBIQF6c7uaVbjCZ4iki9wnGZ5JA8hFZDoREgJCsHxwIhAONgFmVUzsUw +Z/hjjodDMMX9KgZ0pYHSfbKoNRuJzZ+DAiEAp9ooC2igvUZ3rEkDYScPJuXpGXdS +G09TnkVNNsn8RcUCIQCQ2ERMFwOFgHmrNRi1uCrY5Zag+Cv7ELE8X4U9XsLbqwIh +ALM7UlYJ1ZKAFlK2cnqUCiLoD7Ah9eVfg+rOTUVMOa3v +-----END RSA PRIVATE KEY----- diff --git a/docker_test/key_ecdsa_prime256v1.pem b/docker_test/key_ecdsa_prime256v1.pem new file mode 100644 index 0000000..4e1a0f1 --- /dev/null +++ b/docker_test/key_ecdsa_prime256v1.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIP5zy1nQDeAkFKDZ1F/ur26G7SBeu1HbCgbNLwFVUzrroAoGCCqGSM49 +AwEHoUQDQgAEQkb8ffhxrztFHu3PiZ4MarPyxX6dJKXb5UEkVbczdbzkLzhOXHlY +blnXr4a2mwrSEFPzjCORSjQqk99jv90IVg== +-----END EC PRIVATE KEY----- diff --git a/docker_test/key_notes.txt b/docker_test/key_notes.txt new file mode 100644 index 0000000..005dda6 --- /dev/null +++ b/docker_test/key_notes.txt @@ -0,0 +1,22 @@ +There is one Certificate Authority in this directory: ca_cert.pem / ca_key.pem. + +This CA directly signed these certificates (with their corresponding keys): + * cert_512.crt / key_512.pem + * cert_1024.crt / key_3072.pem + * cert_2048.crt / key_2048.pem + * cert_3072.crt / key_3072.pem + +The 512, 1024, 2048, and 3072 refer to the RSA key size. + +--- + +To generate new keys, and sign them by the CA: + +1.) Generate the key. + + * For RSA keys: openssl genrsa -out key.pem 1024 + * For ECDSA keys: openssl ecparam -name prime256v1 -genkey -noout -out key.pem + +2.) Make CSR: openssl req -new -key key.pem -out new.csr + +3.) Sign with CA: openssl x509 -req -days 3653 -in new.csr -CA path/to/ca_cert.pem -CAkey path/to/ca_key.pem -CAcreateserial -out new.crt [-md5|-sha1|-sha256] diff --git a/docker_test/nginx_site_client_cert_required b/docker_test/nginx_site_client_cert_required new file mode 100644 index 0000000..16e20e2 --- /dev/null +++ b/docker_test/nginx_site_client_cert_required @@ -0,0 +1,21 @@ +server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + gzip off; + root /var/www/html; + index index.html index.nginx-debian.html; + server_name _; + location / { + try_files $uri $uri/ =404; + } + # Only TLSv1.2 with one cipher is specified, so the test that runs against this + # finishes quicker (all that's needed is the HTTP response of one successful + # TLS connection). + ssl_protocols TLSv1.2; + ssl_ciphers ECDHE-RSA-CHACHA20-POLY1305; + ssl_prefer_server_ciphers on; + ssl_certificate /etc/ssl/cert_3072.crt; + ssl_certificate_key /etc/ssl/key_3072.pem; + ssl_client_certificate /etc/ssl/ca_cert.pem; + ssl_verify_client on; +} diff --git a/docker_test/nginx_test9.conf b/docker_test/nginx_test9.conf new file mode 100644 index 0000000..aea676c --- /dev/null +++ b/docker_test/nginx_test9.conf @@ -0,0 +1,21 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; +daemon off; + +events { + worker_connections 768; +} + +http { + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + include /etc/nginx/mime.types; + default_type application/octet-stream; + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + include /etc/nginx/sites-available/nginx_site_client_cert_required; +} diff --git a/missing_ciphersuites.h b/missing_ciphersuites.h new file mode 100644 index 0000000..dcdf7d4 --- /dev/null +++ b/missing_ciphersuites.h @@ -0,0 +1,629 @@ +#ifndef _MISSING_CIPHERSUITES_H +#define _MISSING_CIPHERSUITES_H + + +/* At run-time, the findMissingCiphers() function will enumerate all the ciphers that OpenSSL knows of, and compares them each to the missing_ciphersuites list. Afterwards, the 'check_tls_versions' field will have the set of TLS versions that OpenSSL does not have an implementation for (i.e.: if the TLS_RSA_WITH_IDEA_CBC_SHA cipher is set to V1_2, then OpenSSL has an implementation for it for TLS v1.0 and v1.1, but not for v1.2). */ + + +#define V1_0 (1) +#define V1_1 (1 << 1) +#define V1_2 (1 << 2) +#define VALL (V1_0 | V1_1 | V1_2) + + +struct missing_ciphersuite { + unsigned short id; /* TLS protocol ID. */ + char protocol_name[48]; /* IANA name, as defined in the RFCs. */ + int bits; /* Bit strength of the cipher. -1 if unknown. */ + unsigned int check_tls_versions; /* OR'ed list of V1_? defines. Refers to TLS version that OpenSSL does not have a ciphersuite implementation for. Hence, it should be tested under this version of TLS. */ + unsigned int accepted_tls_versions; /* OR'ed list of V1_? defines. Set at run-time if this ciphersuite was accepted by the server by the specified TLS version. */ +}; + + +/* Auto-generated by ./iana_tls_ciphersuite_parser.py on December 10, 2019. */ +struct missing_ciphersuite missing_ciphersuites[] = { + {0x0000, "TLS_NULL_WITH_NULL_NULL", -1, VALL, 0}, + {0x0001, "TLS_RSA_WITH_NULL_MD5", -1, VALL, 0}, + {0x0002, "TLS_RSA_WITH_NULL_SHA", -1, VALL, 0}, + {0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", 40, VALL, 0}, + {0x0004, "TLS_RSA_WITH_RC4_128_MD5", 128, VALL, 0}, + {0x0005, "TLS_RSA_WITH_RC4_128_SHA", 128, VALL, 0}, + {0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 40, VALL, 0}, + {0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA", 128, VALL, 0}, + {0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, + {0x0009, "TLS_RSA_WITH_DES_CBC_SHA", 56, VALL, 0}, + {0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x000B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, + {0x000C, "TLS_DH_DSS_WITH_DES_CBC_SHA", 56, VALL, 0}, + {0x000D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x000E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, + {0x000F, "TLS_DH_RSA_WITH_DES_CBC_SHA", 56, VALL, 0}, + {0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, + {0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA", 56, VALL, 0}, + {0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, + {0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA", 56, VALL, 0}, + {0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", 40, VALL, 0}, + {0x0018, "TLS_DH_anon_WITH_RC4_128_MD5", 128, VALL, 0}, + {0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, + {0x001A, "TLS_DH_anon_WITH_DES_CBC_SHA", 56, VALL, 0}, + {0x001B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x001E, "TLS_KRB5_WITH_DES_CBC_SHA", 56, VALL, 0}, + {0x001F, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x0020, "TLS_KRB5_WITH_RC4_128_SHA", 128, VALL, 0}, + {0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA", 128, VALL, 0}, + {0x0022, "TLS_KRB5_WITH_DES_CBC_MD5", 56, VALL, 0}, + {0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5", 112, VALL, 0}, + {0x0024, "TLS_KRB5_WITH_RC4_128_MD5", 128, VALL, 0}, + {0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5", 128, VALL, 0}, + {0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", 56, VALL, 0}, + {0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 40, VALL, 0}, + {0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA", 40, VALL, 0}, + {0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 56, VALL, 0}, + {0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 40, VALL, 0}, + {0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5", 40, VALL, 0}, + {0x002C, "TLS_PSK_WITH_NULL_SHA", -1, VALL, 0}, + {0x002D, "TLS_DHE_PSK_WITH_NULL_SHA", -1, VALL, 0}, + {0x002E, "TLS_RSA_PSK_WITH_NULL_SHA", -1, VALL, 0}, + {0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x003B, "TLS_RSA_WITH_NULL_SHA256", -1, VALL, 0}, + {0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, + {0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, + {0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, + {0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, + {0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, + {0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, + {0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, + {0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, + {0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, + {0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, + {0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, + {0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, + {0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, + {0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, + {0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, + {0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, + {0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, + {0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, + {0x008A, "TLS_PSK_WITH_RC4_128_SHA", 128, VALL, 0}, + {0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA", 128, VALL, 0}, + {0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA", 128, VALL, 0}, + {0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0x0096, "TLS_RSA_WITH_SEED_CBC_SHA", -1, VALL, 0}, + {0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA", -1, VALL, 0}, + {0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA", -1, VALL, 0}, + {0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA", -1, VALL, 0}, + {0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA", -1, VALL, 0}, + {0x009B, "TLS_DH_anon_WITH_SEED_CBC_SHA", -1, VALL, 0}, + {0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x00A8, "TLS_PSK_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x00A9, "TLS_PSK_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x00AA, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x00AB, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x00AC, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x00AD, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x00AE, "TLS_PSK_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x00AF, "TLS_PSK_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, + {0x00B0, "TLS_PSK_WITH_NULL_SHA256", -1, VALL, 0}, + {0x00B1, "TLS_PSK_WITH_NULL_SHA384", -1, VALL, 0}, + {0x00B2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x00B3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, + {0x00B4, "TLS_DHE_PSK_WITH_NULL_SHA256", -1, VALL, 0}, + {0x00B5, "TLS_DHE_PSK_WITH_NULL_SHA384", -1, VALL, 0}, + {0x00B6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0x00B7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, + {0x00B8, "TLS_RSA_PSK_WITH_NULL_SHA256", -1, VALL, 0}, + {0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384", -1, VALL, 0}, + {0x00BA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0x00BB, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0x00BC, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0x00BD, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0x00BE, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0x00BF, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0x00C0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, + {0x00C1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, + {0x00C2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, + {0x00C3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, + {0x00C4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, + {0x00C5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, + {0x00C6, "TLS_SM4_GCM_SM3", 128, VALL, 0}, + {0x00C7, "TLS_SM4_CCM_SM3", 128, VALL, 0}, + {0x1301, "TLS_AES_128_GCM_SHA256", 128, VALL, 0}, + {0x1302, "TLS_AES_256_GCM_SHA384", 256, VALL, 0}, + {0x1303, "TLS_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, + {0x1304, "TLS_AES_128_CCM_SHA256", 128, VALL, 0}, + {0x1305, "TLS_AES_128_CCM_8_SHA256", 128, VALL, 0}, + {0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA", -1, VALL, 0}, + {0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", 128, VALL, 0}, + {0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA", -1, VALL, 0}, + {0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 128, VALL, 0}, + {0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC00B, "TLS_ECDH_RSA_WITH_NULL_SHA", -1, VALL, 0}, + {0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA", 128, VALL, 0}, + {0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA", -1, VALL, 0}, + {0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", 128, VALL, 0}, + {0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC015, "TLS_ECDH_anon_WITH_NULL_SHA", -1, VALL, 0}, + {0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA", 128, VALL, 0}, + {0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, + {0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, + {0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, + {0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, + {0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0xC033, "TLS_ECDHE_PSK_WITH_RC4_128_SHA", 128, VALL, 0}, + {0xC034, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, + {0xC035, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 128, VALL, 0}, + {0xC036, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", 256, VALL, 0}, + {0xC037, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, + {0xC038, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, + {0xC039, "TLS_ECDHE_PSK_WITH_NULL_SHA", -1, VALL, 0}, + {0xC03A, "TLS_ECDHE_PSK_WITH_NULL_SHA256", -1, VALL, 0}, + {0xC03B, "TLS_ECDHE_PSK_WITH_NULL_SHA384", -1, VALL, 0}, + {0xC03C, "TLS_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC03D, "TLS_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC03E, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC03F, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC040, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC041, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC042, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC043, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC044, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC045, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC046, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC047, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC048, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC049, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC04A, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC04B, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC04C, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC04D, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC04E, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC04F, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC050, "TLS_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC051, "TLS_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC052, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC053, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC054, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC055, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC056, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC057, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC058, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC059, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC05A, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC05B, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC05C, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC05D, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC05E, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC05F, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC060, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC061, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC062, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC063, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC064, "TLS_PSK_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC065, "TLS_PSK_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC066, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC067, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC068, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC069, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC06A, "TLS_PSK_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC06B, "TLS_PSK_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC06C, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC06D, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC06E, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC06F, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC070, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC071, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC072, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC073, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC074, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC075, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC076, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC077, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC078, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC079, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC07A, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC07B, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC07C, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC07D, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC07E, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC07F, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC080, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC081, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC082, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC083, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC084, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC085, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC086, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC087, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC088, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC089, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC08A, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC08B, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC08C, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC08D, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC08E, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC08F, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC090, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC091, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC092, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, + {0xC093, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, + {0xC094, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC095, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC096, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC097, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC098, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC099, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC09A, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, + {0xC09B, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, + {0xC09C, "TLS_RSA_WITH_AES_128_CCM", 128, VALL, 0}, + {0xC09D, "TLS_RSA_WITH_AES_256_CCM", 256, VALL, 0}, + {0xC09E, "TLS_DHE_RSA_WITH_AES_128_CCM", 128, VALL, 0}, + {0xC09F, "TLS_DHE_RSA_WITH_AES_256_CCM", 256, VALL, 0}, + {0xC0A0, "TLS_RSA_WITH_AES_128_CCM_8", 128, VALL, 0}, + {0xC0A1, "TLS_RSA_WITH_AES_256_CCM_8", 256, VALL, 0}, + {0xC0A2, "TLS_DHE_RSA_WITH_AES_128_CCM_8", 128, VALL, 0}, + {0xC0A3, "TLS_DHE_RSA_WITH_AES_256_CCM_8", 256, VALL, 0}, + {0xC0A4, "TLS_PSK_WITH_AES_128_CCM", 128, VALL, 0}, + {0xC0A5, "TLS_PSK_WITH_AES_256_CCM", 256, VALL, 0}, + {0xC0A6, "TLS_DHE_PSK_WITH_AES_128_CCM", 128, VALL, 0}, + {0xC0A7, "TLS_DHE_PSK_WITH_AES_256_CCM", 256, VALL, 0}, + {0xC0A8, "TLS_PSK_WITH_AES_128_CCM_8", 128, VALL, 0}, + {0xC0A9, "TLS_PSK_WITH_AES_256_CCM_8", 256, VALL, 0}, + {0xC0AA, "TLS_PSK_DHE_WITH_AES_128_CCM_8", 128, VALL, 0}, + {0xC0AB, "TLS_PSK_DHE_WITH_AES_256_CCM_8", 256, VALL, 0}, + {0xC0AC, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM", 128, VALL, 0}, + {0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM", 256, VALL, 0}, + {0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", 128, VALL, 0}, + {0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8", 256, VALL, 0}, + {0xC0B0, "TLS_ECCPWD_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0xC0B1, "TLS_ECCPWD_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0xC0B2, "TLS_ECCPWD_WITH_AES_128_CCM_SHA256", 128, VALL, 0}, + {0xC0B3, "TLS_ECCPWD_WITH_AES_256_CCM_SHA384", 256, VALL, 0}, + {0xC0B4, "TLS_SHA256_SHA256", -1, VALL, 0}, + {0xC0B5, "TLS_SHA384_SHA384", -1, VALL, 0}, + {0xC100, "TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC", 256, VALL, 0}, + {0xC101, "TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC", 256, VALL, 0}, + {0xC102, "TLS_GOSTR341112_256_WITH_28147_CNT_IMIT", 256, VALL, 0}, + {0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, + {0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, + {0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, + {0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, + {0xCCAC, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, + {0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, + {0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, + {0xD001, "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, + {0xD002, "TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, + {0xD003, "TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256", 128, VALL, 0}, + {0xD005, "TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256", 128, VALL, 0}, + + /* The ciphers below are reserved for private use (see RFC8446). */ + {0xFF00, "PRIVATE_CIPHER_0", -1, VALL, 0}, + {0xFF01, "PRIVATE_CIPHER_1", -1, VALL, 0}, + {0xFF02, "PRIVATE_CIPHER_2", -1, VALL, 0}, + {0xFF03, "PRIVATE_CIPHER_3", -1, VALL, 0}, + {0xFF04, "PRIVATE_CIPHER_4", -1, VALL, 0}, + {0xFF05, "PRIVATE_CIPHER_5", -1, VALL, 0}, + {0xFF06, "PRIVATE_CIPHER_6", -1, VALL, 0}, + {0xFF07, "PRIVATE_CIPHER_7", -1, VALL, 0}, + {0xFF08, "PRIVATE_CIPHER_8", -1, VALL, 0}, + {0xFF09, "PRIVATE_CIPHER_9", -1, VALL, 0}, + {0xFF0A, "PRIVATE_CIPHER_10", -1, VALL, 0}, + {0xFF0B, "PRIVATE_CIPHER_11", -1, VALL, 0}, + {0xFF0C, "PRIVATE_CIPHER_12", -1, VALL, 0}, + {0xFF0D, "PRIVATE_CIPHER_13", -1, VALL, 0}, + {0xFF0E, "PRIVATE_CIPHER_14", -1, VALL, 0}, + {0xFF0F, "PRIVATE_CIPHER_15", -1, VALL, 0}, + {0xFF10, "PRIVATE_CIPHER_16", -1, VALL, 0}, + {0xFF11, "PRIVATE_CIPHER_17", -1, VALL, 0}, + {0xFF12, "PRIVATE_CIPHER_18", -1, VALL, 0}, + {0xFF13, "PRIVATE_CIPHER_19", -1, VALL, 0}, + {0xFF14, "PRIVATE_CIPHER_20", -1, VALL, 0}, + {0xFF15, "PRIVATE_CIPHER_21", -1, VALL, 0}, + {0xFF16, "PRIVATE_CIPHER_22", -1, VALL, 0}, + {0xFF17, "PRIVATE_CIPHER_23", -1, VALL, 0}, + {0xFF18, "PRIVATE_CIPHER_24", -1, VALL, 0}, + {0xFF19, "PRIVATE_CIPHER_25", -1, VALL, 0}, + {0xFF1A, "PRIVATE_CIPHER_26", -1, VALL, 0}, + {0xFF1B, "PRIVATE_CIPHER_27", -1, VALL, 0}, + {0xFF1C, "PRIVATE_CIPHER_28", -1, VALL, 0}, + {0xFF1D, "PRIVATE_CIPHER_29", -1, VALL, 0}, + {0xFF1E, "PRIVATE_CIPHER_30", -1, VALL, 0}, + {0xFF1F, "PRIVATE_CIPHER_31", -1, VALL, 0}, + {0xFF20, "PRIVATE_CIPHER_32", -1, VALL, 0}, + {0xFF21, "PRIVATE_CIPHER_33", -1, VALL, 0}, + {0xFF22, "PRIVATE_CIPHER_34", -1, VALL, 0}, + {0xFF23, "PRIVATE_CIPHER_35", -1, VALL, 0}, + {0xFF24, "PRIVATE_CIPHER_36", -1, VALL, 0}, + {0xFF25, "PRIVATE_CIPHER_37", -1, VALL, 0}, + {0xFF26, "PRIVATE_CIPHER_38", -1, VALL, 0}, + {0xFF27, "PRIVATE_CIPHER_39", -1, VALL, 0}, + {0xFF28, "PRIVATE_CIPHER_40", -1, VALL, 0}, + {0xFF29, "PRIVATE_CIPHER_41", -1, VALL, 0}, + {0xFF2A, "PRIVATE_CIPHER_42", -1, VALL, 0}, + {0xFF2B, "PRIVATE_CIPHER_43", -1, VALL, 0}, + {0xFF2C, "PRIVATE_CIPHER_44", -1, VALL, 0}, + {0xFF2D, "PRIVATE_CIPHER_45", -1, VALL, 0}, + {0xFF2E, "PRIVATE_CIPHER_46", -1, VALL, 0}, + {0xFF2F, "PRIVATE_CIPHER_47", -1, VALL, 0}, + {0xFF30, "PRIVATE_CIPHER_48", -1, VALL, 0}, + {0xFF31, "PRIVATE_CIPHER_49", -1, VALL, 0}, + {0xFF32, "PRIVATE_CIPHER_50", -1, VALL, 0}, + {0xFF33, "PRIVATE_CIPHER_51", -1, VALL, 0}, + {0xFF34, "PRIVATE_CIPHER_52", -1, VALL, 0}, + {0xFF35, "PRIVATE_CIPHER_53", -1, VALL, 0}, + {0xFF36, "PRIVATE_CIPHER_54", -1, VALL, 0}, + {0xFF37, "PRIVATE_CIPHER_55", -1, VALL, 0}, + {0xFF38, "PRIVATE_CIPHER_56", -1, VALL, 0}, + {0xFF39, "PRIVATE_CIPHER_57", -1, VALL, 0}, + {0xFF3A, "PRIVATE_CIPHER_58", -1, VALL, 0}, + {0xFF3B, "PRIVATE_CIPHER_59", -1, VALL, 0}, + {0xFF3C, "PRIVATE_CIPHER_60", -1, VALL, 0}, + {0xFF3D, "PRIVATE_CIPHER_61", -1, VALL, 0}, + {0xFF3E, "PRIVATE_CIPHER_62", -1, VALL, 0}, + {0xFF3F, "PRIVATE_CIPHER_63", -1, VALL, 0}, + {0xFF40, "PRIVATE_CIPHER_64", -1, VALL, 0}, + {0xFF41, "PRIVATE_CIPHER_65", -1, VALL, 0}, + {0xFF42, "PRIVATE_CIPHER_66", -1, VALL, 0}, + {0xFF43, "PRIVATE_CIPHER_67", -1, VALL, 0}, + {0xFF44, "PRIVATE_CIPHER_68", -1, VALL, 0}, + {0xFF45, "PRIVATE_CIPHER_69", -1, VALL, 0}, + {0xFF46, "PRIVATE_CIPHER_70", -1, VALL, 0}, + {0xFF47, "PRIVATE_CIPHER_71", -1, VALL, 0}, + {0xFF48, "PRIVATE_CIPHER_72", -1, VALL, 0}, + {0xFF49, "PRIVATE_CIPHER_73", -1, VALL, 0}, + {0xFF4A, "PRIVATE_CIPHER_74", -1, VALL, 0}, + {0xFF4B, "PRIVATE_CIPHER_75", -1, VALL, 0}, + {0xFF4C, "PRIVATE_CIPHER_76", -1, VALL, 0}, + {0xFF4D, "PRIVATE_CIPHER_77", -1, VALL, 0}, + {0xFF4E, "PRIVATE_CIPHER_78", -1, VALL, 0}, + {0xFF4F, "PRIVATE_CIPHER_79", -1, VALL, 0}, + {0xFF50, "PRIVATE_CIPHER_80", -1, VALL, 0}, + {0xFF51, "PRIVATE_CIPHER_81", -1, VALL, 0}, + {0xFF52, "PRIVATE_CIPHER_82", -1, VALL, 0}, + {0xFF53, "PRIVATE_CIPHER_83", -1, VALL, 0}, + {0xFF54, "PRIVATE_CIPHER_84", -1, VALL, 0}, + {0xFF55, "PRIVATE_CIPHER_85", -1, VALL, 0}, + {0xFF56, "PRIVATE_CIPHER_86", -1, VALL, 0}, + {0xFF57, "PRIVATE_CIPHER_87", -1, VALL, 0}, + {0xFF58, "PRIVATE_CIPHER_88", -1, VALL, 0}, + {0xFF59, "PRIVATE_CIPHER_89", -1, VALL, 0}, + {0xFF5A, "PRIVATE_CIPHER_90", -1, VALL, 0}, + {0xFF5B, "PRIVATE_CIPHER_91", -1, VALL, 0}, + {0xFF5C, "PRIVATE_CIPHER_92", -1, VALL, 0}, + {0xFF5D, "PRIVATE_CIPHER_93", -1, VALL, 0}, + {0xFF5E, "PRIVATE_CIPHER_94", -1, VALL, 0}, + {0xFF5F, "PRIVATE_CIPHER_95", -1, VALL, 0}, + {0xFF60, "PRIVATE_CIPHER_96", -1, VALL, 0}, + {0xFF61, "PRIVATE_CIPHER_97", -1, VALL, 0}, + {0xFF62, "PRIVATE_CIPHER_98", -1, VALL, 0}, + {0xFF63, "PRIVATE_CIPHER_99", -1, VALL, 0}, + {0xFF64, "PRIVATE_CIPHER_100", -1, VALL, 0}, + {0xFF65, "PRIVATE_CIPHER_101", -1, VALL, 0}, + {0xFF66, "PRIVATE_CIPHER_102", -1, VALL, 0}, + {0xFF67, "PRIVATE_CIPHER_103", -1, VALL, 0}, + {0xFF68, "PRIVATE_CIPHER_104", -1, VALL, 0}, + {0xFF69, "PRIVATE_CIPHER_105", -1, VALL, 0}, + {0xFF6A, "PRIVATE_CIPHER_106", -1, VALL, 0}, + {0xFF6B, "PRIVATE_CIPHER_107", -1, VALL, 0}, + {0xFF6C, "PRIVATE_CIPHER_108", -1, VALL, 0}, + {0xFF6D, "PRIVATE_CIPHER_109", -1, VALL, 0}, + {0xFF6E, "PRIVATE_CIPHER_110", -1, VALL, 0}, + {0xFF6F, "PRIVATE_CIPHER_111", -1, VALL, 0}, + {0xFF70, "PRIVATE_CIPHER_112", -1, VALL, 0}, + {0xFF71, "PRIVATE_CIPHER_113", -1, VALL, 0}, + {0xFF72, "PRIVATE_CIPHER_114", -1, VALL, 0}, + {0xFF73, "PRIVATE_CIPHER_115", -1, VALL, 0}, + {0xFF74, "PRIVATE_CIPHER_116", -1, VALL, 0}, + {0xFF75, "PRIVATE_CIPHER_117", -1, VALL, 0}, + {0xFF76, "PRIVATE_CIPHER_118", -1, VALL, 0}, + {0xFF77, "PRIVATE_CIPHER_119", -1, VALL, 0}, + {0xFF78, "PRIVATE_CIPHER_120", -1, VALL, 0}, + {0xFF79, "PRIVATE_CIPHER_121", -1, VALL, 0}, + {0xFF7A, "PRIVATE_CIPHER_122", -1, VALL, 0}, + {0xFF7B, "PRIVATE_CIPHER_123", -1, VALL, 0}, + {0xFF7C, "PRIVATE_CIPHER_124", -1, VALL, 0}, + {0xFF7D, "PRIVATE_CIPHER_125", -1, VALL, 0}, + {0xFF7E, "PRIVATE_CIPHER_126", -1, VALL, 0}, + {0xFF7F, "PRIVATE_CIPHER_127", -1, VALL, 0}, + {0xFF80, "PRIVATE_CIPHER_128", -1, VALL, 0}, + {0xFF81, "PRIVATE_CIPHER_129", -1, VALL, 0}, + {0xFF82, "PRIVATE_CIPHER_130", -1, VALL, 0}, + {0xFF83, "PRIVATE_CIPHER_131", -1, VALL, 0}, + {0xFF84, "PRIVATE_CIPHER_132", -1, VALL, 0}, + {0xFF85, "PRIVATE_CIPHER_133", -1, VALL, 0}, + {0xFF86, "PRIVATE_CIPHER_134", -1, VALL, 0}, + {0xFF87, "PRIVATE_CIPHER_135", -1, VALL, 0}, + {0xFF88, "PRIVATE_CIPHER_136", -1, VALL, 0}, + {0xFF89, "PRIVATE_CIPHER_137", -1, VALL, 0}, + {0xFF8A, "PRIVATE_CIPHER_138", -1, VALL, 0}, + {0xFF8B, "PRIVATE_CIPHER_139", -1, VALL, 0}, + {0xFF8C, "PRIVATE_CIPHER_140", -1, VALL, 0}, + {0xFF8D, "PRIVATE_CIPHER_141", -1, VALL, 0}, + {0xFF8E, "PRIVATE_CIPHER_142", -1, VALL, 0}, + {0xFF8F, "PRIVATE_CIPHER_143", -1, VALL, 0}, + {0xFF90, "PRIVATE_CIPHER_144", -1, VALL, 0}, + {0xFF91, "PRIVATE_CIPHER_145", -1, VALL, 0}, + {0xFF92, "PRIVATE_CIPHER_146", -1, VALL, 0}, + {0xFF93, "PRIVATE_CIPHER_147", -1, VALL, 0}, + {0xFF94, "PRIVATE_CIPHER_148", -1, VALL, 0}, + {0xFF95, "PRIVATE_CIPHER_149", -1, VALL, 0}, + {0xFF96, "PRIVATE_CIPHER_150", -1, VALL, 0}, + {0xFF97, "PRIVATE_CIPHER_151", -1, VALL, 0}, + {0xFF98, "PRIVATE_CIPHER_152", -1, VALL, 0}, + {0xFF99, "PRIVATE_CIPHER_153", -1, VALL, 0}, + {0xFF9A, "PRIVATE_CIPHER_154", -1, VALL, 0}, + {0xFF9B, "PRIVATE_CIPHER_155", -1, VALL, 0}, + {0xFF9C, "PRIVATE_CIPHER_156", -1, VALL, 0}, + {0xFF9D, "PRIVATE_CIPHER_157", -1, VALL, 0}, + {0xFF9E, "PRIVATE_CIPHER_158", -1, VALL, 0}, + {0xFF9F, "PRIVATE_CIPHER_159", -1, VALL, 0}, + {0xFFA0, "PRIVATE_CIPHER_160", -1, VALL, 0}, + {0xFFA1, "PRIVATE_CIPHER_161", -1, VALL, 0}, + {0xFFA2, "PRIVATE_CIPHER_162", -1, VALL, 0}, + {0xFFA3, "PRIVATE_CIPHER_163", -1, VALL, 0}, + {0xFFA4, "PRIVATE_CIPHER_164", -1, VALL, 0}, + {0xFFA5, "PRIVATE_CIPHER_165", -1, VALL, 0}, + {0xFFA6, "PRIVATE_CIPHER_166", -1, VALL, 0}, + {0xFFA7, "PRIVATE_CIPHER_167", -1, VALL, 0}, + {0xFFA8, "PRIVATE_CIPHER_168", -1, VALL, 0}, + {0xFFA9, "PRIVATE_CIPHER_169", -1, VALL, 0}, + {0xFFAA, "PRIVATE_CIPHER_170", -1, VALL, 0}, + {0xFFAB, "PRIVATE_CIPHER_171", -1, VALL, 0}, + {0xFFAC, "PRIVATE_CIPHER_172", -1, VALL, 0}, + {0xFFAD, "PRIVATE_CIPHER_173", -1, VALL, 0}, + {0xFFAE, "PRIVATE_CIPHER_174", -1, VALL, 0}, + {0xFFAF, "PRIVATE_CIPHER_175", -1, VALL, 0}, + {0xFFB0, "PRIVATE_CIPHER_176", -1, VALL, 0}, + {0xFFB1, "PRIVATE_CIPHER_177", -1, VALL, 0}, + {0xFFB2, "PRIVATE_CIPHER_178", -1, VALL, 0}, + {0xFFB3, "PRIVATE_CIPHER_179", -1, VALL, 0}, + {0xFFB4, "PRIVATE_CIPHER_180", -1, VALL, 0}, + {0xFFB5, "PRIVATE_CIPHER_181", -1, VALL, 0}, + {0xFFB6, "PRIVATE_CIPHER_182", -1, VALL, 0}, + {0xFFB7, "PRIVATE_CIPHER_183", -1, VALL, 0}, + {0xFFB8, "PRIVATE_CIPHER_184", -1, VALL, 0}, + {0xFFB9, "PRIVATE_CIPHER_185", -1, VALL, 0}, + {0xFFBA, "PRIVATE_CIPHER_186", -1, VALL, 0}, + {0xFFBB, "PRIVATE_CIPHER_187", -1, VALL, 0}, + {0xFFBC, "PRIVATE_CIPHER_188", -1, VALL, 0}, + {0xFFBD, "PRIVATE_CIPHER_189", -1, VALL, 0}, + {0xFFBE, "PRIVATE_CIPHER_190", -1, VALL, 0}, + {0xFFBF, "PRIVATE_CIPHER_191", -1, VALL, 0}, + {0xFFC0, "PRIVATE_CIPHER_192", -1, VALL, 0}, + {0xFFC1, "PRIVATE_CIPHER_193", -1, VALL, 0}, + {0xFFC2, "PRIVATE_CIPHER_194", -1, VALL, 0}, + {0xFFC3, "PRIVATE_CIPHER_195", -1, VALL, 0}, + {0xFFC4, "PRIVATE_CIPHER_196", -1, VALL, 0}, + {0xFFC5, "PRIVATE_CIPHER_197", -1, VALL, 0}, + {0xFFC6, "PRIVATE_CIPHER_198", -1, VALL, 0}, + {0xFFC7, "PRIVATE_CIPHER_199", -1, VALL, 0}, + {0xFFC8, "PRIVATE_CIPHER_200", -1, VALL, 0}, + {0xFFC9, "PRIVATE_CIPHER_201", -1, VALL, 0}, + {0xFFCA, "PRIVATE_CIPHER_202", -1, VALL, 0}, + {0xFFCB, "PRIVATE_CIPHER_203", -1, VALL, 0}, + {0xFFCC, "PRIVATE_CIPHER_204", -1, VALL, 0}, + {0xFFCD, "PRIVATE_CIPHER_205", -1, VALL, 0}, + {0xFFCE, "PRIVATE_CIPHER_206", -1, VALL, 0}, + {0xFFCF, "PRIVATE_CIPHER_207", -1, VALL, 0}, + {0xFFD0, "PRIVATE_CIPHER_208", -1, VALL, 0}, + {0xFFD1, "PRIVATE_CIPHER_209", -1, VALL, 0}, + {0xFFD2, "PRIVATE_CIPHER_210", -1, VALL, 0}, + {0xFFD3, "PRIVATE_CIPHER_211", -1, VALL, 0}, + {0xFFD4, "PRIVATE_CIPHER_212", -1, VALL, 0}, + {0xFFD5, "PRIVATE_CIPHER_213", -1, VALL, 0}, + {0xFFD6, "PRIVATE_CIPHER_214", -1, VALL, 0}, + {0xFFD7, "PRIVATE_CIPHER_215", -1, VALL, 0}, + {0xFFD8, "PRIVATE_CIPHER_216", -1, VALL, 0}, + {0xFFD9, "PRIVATE_CIPHER_217", -1, VALL, 0}, + {0xFFDA, "PRIVATE_CIPHER_218", -1, VALL, 0}, + {0xFFDB, "PRIVATE_CIPHER_219", -1, VALL, 0}, + {0xFFDC, "PRIVATE_CIPHER_220", -1, VALL, 0}, + {0xFFDD, "PRIVATE_CIPHER_221", -1, VALL, 0}, + {0xFFDE, "PRIVATE_CIPHER_222", -1, VALL, 0}, + {0xFFDF, "PRIVATE_CIPHER_223", -1, VALL, 0}, + {0xFFE0, "PRIVATE_CIPHER_224", -1, VALL, 0}, + {0xFFE1, "PRIVATE_CIPHER_225", -1, VALL, 0}, + {0xFFE2, "PRIVATE_CIPHER_226", -1, VALL, 0}, + {0xFFE3, "PRIVATE_CIPHER_227", -1, VALL, 0}, + {0xFFE4, "PRIVATE_CIPHER_228", -1, VALL, 0}, + {0xFFE5, "PRIVATE_CIPHER_229", -1, VALL, 0}, + {0xFFE6, "PRIVATE_CIPHER_230", -1, VALL, 0}, + {0xFFE7, "PRIVATE_CIPHER_231", -1, VALL, 0}, + {0xFFE8, "PRIVATE_CIPHER_232", -1, VALL, 0}, + {0xFFE9, "PRIVATE_CIPHER_233", -1, VALL, 0}, + {0xFFEA, "PRIVATE_CIPHER_234", -1, VALL, 0}, + {0xFFEB, "PRIVATE_CIPHER_235", -1, VALL, 0}, + {0xFFEC, "PRIVATE_CIPHER_236", -1, VALL, 0}, + {0xFFED, "PRIVATE_CIPHER_237", -1, VALL, 0}, + {0xFFEE, "PRIVATE_CIPHER_238", -1, VALL, 0}, + {0xFFEF, "PRIVATE_CIPHER_239", -1, VALL, 0}, + {0xFFF0, "PRIVATE_CIPHER_240", -1, VALL, 0}, + {0xFFF1, "PRIVATE_CIPHER_241", -1, VALL, 0}, + {0xFFF2, "PRIVATE_CIPHER_242", -1, VALL, 0}, + {0xFFF3, "PRIVATE_CIPHER_243", -1, VALL, 0}, + {0xFFF4, "PRIVATE_CIPHER_244", -1, VALL, 0}, + {0xFFF5, "PRIVATE_CIPHER_245", -1, VALL, 0}, + {0xFFF6, "PRIVATE_CIPHER_246", -1, VALL, 0}, + {0xFFF7, "PRIVATE_CIPHER_247", -1, VALL, 0}, + {0xFFF8, "PRIVATE_CIPHER_248", -1, VALL, 0}, + {0xFFF9, "PRIVATE_CIPHER_249", -1, VALL, 0}, + {0xFFFA, "PRIVATE_CIPHER_250", -1, VALL, 0}, + {0xFFFB, "PRIVATE_CIPHER_251", -1, VALL, 0}, + {0xFFFC, "PRIVATE_CIPHER_252", -1, VALL, 0}, + {0xFFFD, "PRIVATE_CIPHER_253", -1, VALL, 0}, + {0xFFFE, "PRIVATE_CIPHER_254", -1, VALL, 0}, + {0xFFFF, "PRIVATE_CIPHER_255", -1, VALL, 0}, +}; + +#endif diff --git a/sslscan.c b/sslscan.c index 92032af..5f210d4 100644 --- a/sslscan.c +++ b/sslscan.c @@ -81,6 +81,9 @@ #include "win32bit-compat.h" #endif #endif + + const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); + #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #endif @@ -91,6 +94,7 @@ #endif #include #include +#include #include #include #include @@ -114,8 +118,19 @@ #include #endif +/* Format specifier for printing a size_t. */ +#ifdef _WIN32 + #define SIZE_T_FMT PRIu64 +#else + #define SIZE_T_FMT "zu" +#endif + #include "sslscan.h" +#if OPENSSL_VERSION_NUMBER < 0x1010100fL +#error "OpenSSL v1.1.1 or later is required!" +#endif + /* Borrowed from tortls.c to dance with OpenSSL on many platforms, with * many versions and releases of OpenSSL. */ /** Does the run-time openssl version look like we need @@ -133,22 +148,35 @@ static int xml_to_stdout = 0; unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; } #endif -// Helper function to recv from socket until EOF or an error -static ssize_t recvall(int sockfd, void *buf, size_t len, int flags) +const SSL_METHOD *TLSv1_3_client_method(void) { - size_t remaining = len; - char *bufptr = buf; - do - { - ssize_t actual = recv(sockfd, bufptr, remaining, flags); - if (actual <= 0) // premature eof or an error? - { - return actual; - } - bufptr += actual; - remaining -= actual; - } while (remaining != 0); - return (ssize_t) len; + return TLS_client_method(); +} + +const SSL_METHOD *TLSv1_3_method(void) +{ + return TLS_method(); +} + +/* Callback set through SSL_set_security_callback() and SSL_CTX_set_security_callback(). Allows all weak algorithms. */ +static int security_callback_allow_all(const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex) { + return 1; +} + +/* Creates an SSL_CTX using SSL_CTX_new(), sets the security level to 0, and sets the permissive security callback on it. Free with FREE_CTX(). */ +SSL_CTX *new_CTX(const SSL_METHOD *method) { + SSL_CTX *ret = SSL_CTX_new(method); + SSL_CTX_set_security_level(ret, 0); + SSL_CTX_set_security_callback(ret, security_callback_allow_all); + return ret; +} + +/* Creates an SSL object using SSL_new(), sets the security level to 0, and sets the permissive security callback on it. Free with FREE_SSL(). */ +SSL *new_SSL(SSL_CTX *ctx) { + SSL *ret = SSL_new(ctx); + SSL_set_security_level(ret, 0); + SSL_set_security_callback(ret, security_callback_allow_all); + return ret; } // Adds Ciphers to the Cipher List structure @@ -161,16 +189,16 @@ int populateCipherList(struct sslCheckOptions *options, const SSL_METHOD *sslMet // STACK_OF is a sign that you should be using C++ :) STACK_OF(SSL_CIPHER) *cipherList; SSL *ssl = NULL; - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); if (options->ctx == NULL) { printf_error("%sERROR: Could not create CTX object.%s\n", COL_RED, RESET); return false; } - SSL_CTX_set_cipher_list(options->ctx, "ALL:COMPLEMENTOFALL"); - ssl = SSL_new(options->ctx); + SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL); + ssl = new_SSL(options->ctx); if (ssl == NULL) { printf_error("%sERROR: Could not create SSL object.%s\n", COL_RED, RESET); - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); return false; } cipherList = SSL_get_ciphers(ssl); @@ -199,8 +227,8 @@ int populateCipherList(struct sslCheckOptions *options, const SSL_METHOD *sslMet SSL_CIPHER_description(sk_SSL_CIPHER_value(cipherList, loop), sslCipherPointer->description, sizeof(sslCipherPointer->description) - 1); sslCipherPointer->bits = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(cipherList, loop), &tempInt); } - SSL_free(ssl); - SSL_CTX_free(options->ctx); + FREE_SSL(ssl); + FREE_CTX(options->ctx); return returnCode; } @@ -236,7 +264,7 @@ int readOrLogAndClose(int fd, void* buffer, size_t len, const struct sslCheckOpt if (len < 2) return 1; - n = recvall(fd, buffer, len - 1, 0); + n = recv(fd, buffer, len - 1, 0); if (n < 0 && errno != 11) { printf_error("%s ERROR: error reading from %s:%d: %s%s\n", COL_RED, options->host, options->port, strerror(errno), RESET); @@ -567,7 +595,7 @@ int tcpConnect(struct sslCheckOptions *options) send(socketDescriptor, "\x00\x00\x00\x08\x04\xd2\x16\x2f", 8, 0); // Read reply byte - if (1 != recvall(socketDescriptor, &buffer, 1, 0)) { + if (1 != recv(socketDescriptor, &buffer, 1, 0)) { printf_error("%s ERROR: unexpected EOF reading from %s:%d%s\n", COL_RED, options->host, options->port, RESET); return 0; } @@ -591,7 +619,7 @@ int tcpConnect(struct sslCheckOptions *options) send(socketDescriptor, "\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00", 19, 0); // Read reply header - if (4 != recvall(socketDescriptor, buffer, 4, 0)) { + if (4 != recv(socketDescriptor, buffer, 4, 0)) { printf_error("%s ERROR: unexpected EOF reading from %s:%d%s\n", COL_RED, options->host, options->port, RESET); return 0; } @@ -605,7 +633,7 @@ int tcpConnect(struct sslCheckOptions *options) } // Read reply data - if (readlen != recvall(socketDescriptor, buffer, readlen, 0)) { + if (readlen != recv(socketDescriptor, buffer, readlen, 0)) { printf_error("%s ERROR: unexpected EOF reading from %s:%d%s\n", COL_RED, options->host, options->port, RESET); return 0; } @@ -824,18 +852,18 @@ int testCompression(struct sslCheckOptions *options, const SSL_METHOD *sslMethod int socketDescriptor = 0; SSL *ssl = NULL; BIO *cipherConnectionBio; - SSL_SESSION session; + SSL_SESSION *session; // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); tls_reneg_init(options); if (options->ctx != NULL) { - if (SSL_CTX_set_cipher_list(options->ctx, "ALL:COMPLEMENTOFALL") != 0) + if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... @@ -845,7 +873,7 @@ int testCompression(struct sslCheckOptions *options, const SSL_METHOD *sslMethod if (status == true) { // Create SSL object... - ssl = SSL_new(options->ctx); + ssl = new_SSL(options->ctx); #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL ) // Make sure we can connect to insecure servers @@ -874,16 +902,16 @@ int testCompression(struct sslCheckOptions *options, const SSL_METHOD *sslMethod // Connect SSL over socket SSL_connect(ssl); - session = *SSL_get_session(ssl); + session = SSL_get_session(ssl); #ifndef OPENSSL_NO_COMP // Make sure zlib is actually present - if (COMP_zlib()->type != NID_undef) + if (sk_SSL_COMP_num(SSL_COMP_get_compression_methods()) != 0) { printf_xml(" \n", - session.compress_meth); + SSL_SESSION_get_compress_id(session)); - if (session.compress_meth == 0) + if (SSL_SESSION_get_compress_id(session) == 0) { printf("Compression %sdisabled%s\n\n", COL_GREEN, RESET); } @@ -903,7 +931,7 @@ int testCompression(struct sslCheckOptions *options, const SSL_METHOD *sslMethod SSL_shutdown(ssl); // Free SSL object - SSL_free(ssl); + FREE_SSL(ssl); } else { @@ -918,7 +946,7 @@ int testCompression(struct sslCheckOptions *options, const SSL_METHOD *sslMethod printf_error("%s ERROR: Could set cipher.%s\n", COL_RED, RESET); } // Free CTX Object - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); } // Error Creating Context Object else @@ -967,7 +995,7 @@ int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) if (socketDescriptor != 0) { // Setup Context Object... - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); tls_reneg_init(options); if (options->ctx != NULL) { @@ -975,7 +1003,7 @@ int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { SSL_CTX_set_mode(options->ctx, SSL_MODE_SEND_FALLBACK_SCSV); } - if (SSL_CTX_set_cipher_list(options->ctx, "ALL:COMPLEMENTOFALL") != 0) + if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... @@ -985,7 +1013,7 @@ int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) if (status == true) { // Create SSL object... - ssl = SSL_new(options->ctx); + ssl = new_SSL(options->ctx); #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL ) // Make sure we can connect to insecure servers @@ -1013,36 +1041,37 @@ int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) // Connect SSL over socket connStatus = SSL_connect(ssl); - if (connStatus) + if (connStatus > 0) { if (!downgraded) { sslversion = SSL_version(ssl); -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - if (sslversion == TLS1_2_VERSION) + if (sslversion == TLS1_3_VERSION) { - secondMethod = TLSv1_1_client_method(); + secondMethod = TLSv1_2_client_method(); } - else if (sslversion == TLS1_1_VERSION) - { - secondMethod = TLSv1_client_method(); - } else -#endif - if (sslversion == TLS1_VERSION) + else if (sslversion == TLS1_2_VERSION) { - printf("Server only supports TLSv1.0\n\n"); - status = false; - } - else - { - printf("Server doesn't support TLS - skipping TLS Fallback SCSV check\n\n"); - status = false; + secondMethod = TLSv1_1_client_method(); } + else if (sslversion == TLS1_VERSION) + { + secondMethod = TLSv1_client_method(); + } + else if (sslversion == TLS1_VERSION) + { + printf("Server only supports TLSv1.0"); + status = false; + } + else + { + printf("Server doesn't support TLS - skipping TLS Fallback SCSV check\n\n"); + status = false; + } } else { printf("Server %sdoes not%s support TLS Fallback SCSV\n\n", COL_RED, RESET); - printf_xml(" \n"); } } else @@ -1055,7 +1084,6 @@ int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) if (SSL_get_error(ssl, connStatus == 6)) { printf("Server %ssupports%s TLS Fallback SCSV\n\n", COL_GREEN, RESET); - printf_xml(" \n"); status = false; } } @@ -1072,7 +1100,7 @@ int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) SSL_shutdown(ssl); // Free SSL object - SSL_free(ssl); + FREE_SSL(ssl); } else { @@ -1087,7 +1115,7 @@ int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) printf_error("%s ERROR: Could set cipher.%s\n", COL_RED, RESET); } // Free CTX Object - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); } // Error Creating Context Object else @@ -1136,11 +1164,11 @@ int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMeth { // Setup Context Object... - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); tls_reneg_init(options); if (options->ctx != NULL) { - if (SSL_CTX_set_cipher_list(options->ctx, "ALL:COMPLEMENTOFALL") != 0) + if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... @@ -1150,7 +1178,7 @@ int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMeth if (status == true) { // Create SSL object... - ssl = SSL_new(options->ctx); + ssl = new_SSL(options->ctx); #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL ) // Make sure we can connect to insecure servers @@ -1187,10 +1215,11 @@ int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMeth /* Yes, we know what we are doing here. No, we do not treat a renegotiation * as authenticating any earlier-received data. */ - if (use_unsafe_renegotiation_flag) { +/* if (use_unsafe_renegotiation_flag) { printf_verbose("use_unsafe_renegotiation_flag\n"); - ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; - } + SSL_CTX_set_options(ssl,SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); + SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION?? + } */ if (use_unsafe_renegotiation_op) { printf_verbose("use_unsafe_renegotiation_op\n"); SSL_set_options(ssl, @@ -1226,14 +1255,14 @@ int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMeth printf_verbose("Attempting SSL_do_handshake(ssl)\n"); SSL_do_handshake(ssl); // Send renegotiation request to server //TODO :: XXX hanging here - if (SSL_get_state(ssl) == SSL_ST_OK) + if (SSL_get_state(ssl) == TLS_ST_OK) { res = SSL_do_handshake(ssl); // Send renegotiation request to server if( res != 1 ) { printf_error("\n\nSSL_do_handshake() call failed\n"); } - if (SSL_get_state(ssl) == SSL_ST_OK) + if (SSL_get_state(ssl) == TLS_ST_OK) { /* our renegotiation is complete */ renOut->supported = true; @@ -1255,7 +1284,7 @@ int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMeth } // Free SSL object - SSL_free(ssl); + FREE_SSL(ssl); } else { @@ -1272,7 +1301,7 @@ int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMeth printf_error("%s ERROR: Could set cipher.%s\n", COL_RED, RESET); } // Free CTX Object - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); } // Error Creating Context Object else @@ -1303,14 +1332,6 @@ int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMeth const char* printableSslMethod(const SSL_METHOD *sslMethod) { -#ifndef OPENSSL_NO_SSL2 - if (sslMethod == SSLv2_client_method()) - return "SSLv2"; -#endif -#ifndef OPENSSL_NO_SSL3 - if (sslMethod == SSLv3_client_method()) - return "SSLv3"; -#endif if (sslMethod == TLSv1_client_method()) return "TLSv1.0"; #if OPENSSL_VERSION_NUMBER >= 0x10001000L @@ -1319,11 +1340,12 @@ const char* printableSslMethod(const SSL_METHOD *sslMethod) if (sslMethod == TLSv1_2_client_method()) return "TLSv1.2"; #endif + if (sslMethod == TLSv1_3_client_method()) + return "TLSv1.3"; return "unknown SSL_METHOD"; } // Test for Heartbleed - int testHeartbleed(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { // Variables... @@ -1354,6 +1376,10 @@ int testHeartbleed(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) hello[10] = 0x03; } #endif + else if (sslMethod == TLSv1_3_client_method()) + { + hello[10] = 0x03; + } if (send(socketDescriptor, hello, sizeof(hello), 0) <= 0) { printf_error("send() failed: %s\n", strerror(errno)); exit(1); @@ -1375,6 +1401,10 @@ int testHeartbleed(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) hb[2] = 0x03; } #endif + else if (sslMethod == TLSv1_3_client_method()) + { + hb[2] = 0x03; + } if (send(socketDescriptor, hb, sizeof(hb), 0) <= 0) { printf_error("send() failed: %s\n", strerror(errno)); exit(1); @@ -1387,7 +1417,7 @@ int testHeartbleed(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) memset(hbbuf, 0, sizeof(hbbuf)); // Read 5 byte header - int readResult = recvall(socketDescriptor, hbbuf, 5, 0); + int readResult = recv(socketDescriptor, hbbuf, 5, 0); if (readResult <= 0) { break; @@ -1406,7 +1436,7 @@ int testHeartbleed(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) memset(hbbuf, 0, sizeof(hbbuf)); // Read rest of record - readResult = recvall(socketDescriptor, hbbuf, ln, 0); + readResult = recv(socketDescriptor, hbbuf, ln, 0); if (readResult <= 0) { break; @@ -1482,7 +1512,6 @@ int ssl_print_tmp_key(struct sslCheckOptions *options, SSL *s) } printf_xml(" dhebits=\"%d\"", EVP_PKEY_bits(key)); break; -#ifndef OPENSSL_NO_EC case EVP_PKEY_EC: { EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); @@ -1496,7 +1525,17 @@ int ssl_print_tmp_key(struct sslCheckOptions *options, SSL *s) printf(" Curve %s DHE %d", cname, EVP_PKEY_bits(key)); printf_xml(" curve=\"%s\" ecdhebits=\"%d\"", cname, EVP_PKEY_bits(key)); } -#endif + break; + case EVP_PKEY_X25519: + printf(" Curve %s25519%s DHE %d", COL_GREEN, RESET, EVP_PKEY_bits(key)); + printf_xml(" curve=\"25519\" ecdhebits=\"%d\"", EVP_PKEY_bits(key)); + break; + case EVP_PKEY_X448: + printf(" Curve %s448%s DHE %d", COL_GREEN, RESET, EVP_PKEY_bits(key)); + printf_xml(" curve=\"448\" ecdhebits=\"%d\"", EVP_PKEY_bits(key)); + break; + default: + printf(" %sUnknown ID (%d)%s", COL_YELLOW, EVP_PKEY_id(key), RESET); } EVP_PKEY_free(key); return 1; @@ -1504,50 +1543,170 @@ int ssl_print_tmp_key(struct sslCheckOptions *options, SSL *s) return 0; } +int setCipherSuite(struct sslCheckOptions *options, const SSL_METHOD *sslMethod, const char *str) +{ + if(strlen(str)>0) + { + if(sslMethod==TLSv1_3_client_method()) + { + return(SSL_CTX_set_ciphersuites(options->ctx,str)); + } + else + { + return(SSL_CTX_set_cipher_list(options->ctx,str)); + } + } + return 0; +} + +char *cipherRemove(char *str, const char *sub) { + char *p, *q, *r; + if ((q = r = strstr(str, sub)) != NULL) { + size_t len = strlen(sub)+1; + if(q != str) + { + q--; + r--; + } + while ((r = strstr(p = r + len, sub)) != NULL) { + while (p < r) + *q++ = *p++; + } + while ((*q++ = *p++) != '\0') + continue; + } + return str; +} + +/* Outputs an accepted cipher to the console and XML file. */ +void outputCipher(struct sslCheckOptions *options, SSL *ssl, const char *cleanSslMethod, uint32_t cipherid, const char *ciphername, int cipherbits, int cipher_accepted, unsigned int milliseconds_elapsed, char *http_code) { + char hexCipherId[8] = {0}; + unsigned int tempInt = 0; + + + printf_xml(" cipherstring, CIPHERSUITE_LIST_ALL) && strcmp(options->cipherstring, TLSV13_CIPHERSUITES)) { + printf_xml("accepted\""); + printf("Accepted "); + } + else { + printf_xml("preferred\""); + printf("%sPreferred%s ", COL_GREEN, RESET); + } + + if (options->http == true) { + printf("%s", http_code); + printf_xml(" http=\"%s\"", http_code); + } + + printf_xml(" sslversion=\"%s\"", cleanSslMethod); + if (strcmp(cleanSslMethod, "TLSv1.3") == 0) { + printf("%sTLSv1.3%s ", COL_GREEN, RESET); + } + else if (strcmp(cleanSslMethod, "TLSv1.0") == 0) { + printf("%sTLSv1.0%s ", COL_YELLOW, RESET); + } else + printf("%s ", cleanSslMethod); + + if (cipherbits < 10) + tempInt = 2; + else if (cipherbits < 100) + tempInt = 1; + + if (cipherbits == -1) { /* When missing ciphers are tested, and we don't have a reasonable guess. */ + printf("%s??%s bits ", COL_YELLOW, RESET); + } else if (cipherbits == 0) { + printf("%s%d%s bits ", COL_RED_BG, cipherbits, RESET); + } else if (cipherbits >= 112) { + printf("%s%d%s bits ", COL_GREEN, cipherbits, RESET); + } else if (cipherbits > 56) { + printf("%s%d%s bits ", COL_YELLOW, cipherbits, RESET); + } else + printf("%s%d%s bits ", COL_RED, cipherbits, RESET); + + while (tempInt != 0) { + tempInt--; + printf(" "); + } + + snprintf(hexCipherId, sizeof(hexCipherId) - 1, "0x%04X", cipherid); + if (options->showCipherIds == true) + printf("%8s ", hexCipherId); + + printf_xml(" bits=\"%d\" cipher=\"%s\" id=\"%s\"", cipherbits, ciphername, hexCipherId); + if (strstr(ciphername, "NULL")) { + printf("%s%-29s%s", COL_RED_BG, ciphername, RESET); + } else if (strstr(ciphername, "ADH") || strstr(ciphername, "AECDH") || strstr(ciphername, "_anon_")) { + printf("%s%-29s%s", COL_PURPLE, ciphername, RESET); + } else if (strstr(ciphername, "EXP")) { + printf("%s%-29s%s", COL_RED, ciphername, RESET); + } else if (strstr(ciphername, "RC4") || strstr(ciphername, "DES")) { + printf("%s%-29s%s", COL_YELLOW, ciphername, RESET); + } else if (strstr(ciphername, "_SM4_")) { /* Developed by Chinese government */ + printf("%s%-29s%s", COL_YELLOW, ciphername, RESET); + } else if (strstr(ciphername, "_GOSTR341112_")) { /* Developed by Russian government */ + printf("%s%-29s%s", COL_YELLOW, ciphername, RESET); + } else if ((strstr(ciphername, "CHACHA20") || (strstr(ciphername, "GCM"))) && strstr(ciphername, "DHE")) { + printf("%s%-29s%s", COL_GREEN, ciphername, RESET); + } else { + printf("%-29s", ciphername); + } + + if ((options->cipher_details == true) && (ssl != NULL)) + ssl_print_tmp_key(options, ssl); + + // Timing + if (options->showTimes) { + printf(" %s%ums%s", COL_GREY, milliseconds_elapsed, RESET); + printf_xml(" time=\"%u\"", milliseconds_elapsed); + } + + printf("\n"); + } + + printf_xml(" />\n"); +} // Test a cipher... int testCipher(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { // Variables... - int cipherStatus; + int cipherStatus = 0; int status = true; int socketDescriptor = 0; SSL *ssl = NULL; - BIO *cipherConnectionBio; - BIO *stdoutBIO = NULL; - int tempInt; - char requestBuffer[200]; - char buffer[50]; - char hexCipherId[10]; + BIO *cipherConnectionBio = NULL; + char requestBuffer[256]; + char buffer[64]; + char http_code[64]; int resultSize = 0; - int cipherbits; - char *strength; - uint32_t cipherid; - const SSL_CIPHER *sslCipherPointer; + int cipherbits = -1; + uint32_t cipherid = 0; + const SSL_CIPHER *sslCipherPointer = NULL; const char *cleanSslMethod = printableSslMethod(sslMethod); - struct timeval tval_start, tval_end, tval_elapsed; + const char *ciphername = NULL; + struct timeval tval_start = {0}; + unsigned int milliseconds_elapsed = 0; + + + memset(requestBuffer, 0, sizeof(requestBuffer)); + memset(buffer, 0, sizeof(buffer)); + memset(http_code, 0, sizeof(http_code)); + if (options->showTimes) { gettimeofday(&tval_start, NULL); } - - - // Create request buffer... - memset(requestBuffer, 0, 200); - snprintf(requestBuffer, 199, "GET / HTTP/1.0\r\nUser-Agent: SSLScan\r\nHost: %s\r\n\r\n", options->host); - // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { - if (SSL_CTX_set_cipher_list(options->ctx, options->cipherstring) != 0) + if (setCipherSuite(options, sslMethod, options->cipherstring)) { - // Create SSL object... - ssl = SSL_new(options->ctx); - - + ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO @@ -1556,10 +1715,8 @@ int testCipher(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); -#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) // This enables TLS SNI SSL_set_tlsext_host_name (ssl, options->sniname); -#endif // Connect SSL over socket cipherStatus = SSL_connect(ssl); @@ -1569,202 +1726,83 @@ int testCipher(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) if (cipherStatus == 0) { - SSL_free(ssl); return false; } else if (cipherStatus != 1) { - tempInt = SSL_get_error(ssl, cipherStatus); - printf_verbose("SSL_get_error(ssl, cipherStatus) returned: %d (%s)\n", tempInt, SSL_ERR_to_string(tempInt)); - - // I'd rather use ERR_print_errors(BIO) instead of this loop, but it needs a BIO for stdout/stderr which we - // don't have yet. - while (ERR_peek_error() > 0) - { - printf_verbose("[%s:%s@%d]:%s\n", __FILE__, __func__, __LINE__, ERR_error_string(ERR_peek_error(), NULL)); - // Dequeue the error, since we only peeked at it. Can't put this in the line above or we'll loop - // forever when not in verbose mode. - ERR_get_error(); - } - SSL_free(ssl); + printf_verbose("SSL_get_error(ssl, cipherStatus) said: %d\n", SSL_get_error(ssl, cipherStatus)); return false; } cipherid = SSL_CIPHER_get_id(sslCipherPointer); cipherid = cipherid & 0x00ffffff; // remove first byte which is the version (0x03 for TLSv1/SSLv3) - // Show Cipher Status - printf_xml(" cipherstring, "ALL:eNULL")) - { - printf_xml("accepted\""); - printf("Accepted "); - } - else - { - printf_xml("preferred\""); - printf("%sPreferred%s ", COL_GREEN, RESET); - } if (options->http == true) { - - // Stdout BIO... - if (!xml_to_stdout) { - stdoutBIO = BIO_new(BIO_s_file()); - BIO_set_fp(stdoutBIO, stdout, BIO_NOCLOSE); - } + // Create request buffer... + snprintf(requestBuffer, sizeof(requestBuffer) - 1, "GET / HTTP/1.0\r\nUser-Agent: SSLScan\r\nHost: %s\r\n\r\n", options->host); // HTTP Get... - SSL_write(ssl, requestBuffer, sizeof(requestBuffer)); - memset(buffer ,0 , 50); - resultSize = SSL_read(ssl, buffer, 49); + SSL_write(ssl, requestBuffer, strlen(requestBuffer)); + memset(buffer, 0, sizeof(buffer)); + resultSize = SSL_read(ssl, buffer, sizeof(buffer) - 1); if (resultSize > 9) { int loop = 0; - for (loop = 9; (loop < 49) && (buffer[loop] != 0) && (buffer[loop] != '\r') && (buffer[loop] != '\n'); loop++) + for (loop = 9; (loop < sizeof(buffer) - 1) && (buffer[loop] != 0) && (buffer[loop] != '\r') && (buffer[loop] != '\n'); loop++) { } buffer[loop] = 0; - // Output HTTP code... - printf("%s", buffer + 9); + strncpy(http_code, buffer + 9, sizeof(http_code) - 1); loop = strlen(buffer + 9); while (loop < 17) { loop++; - printf(" "); + strncat(http_code, " ", sizeof(http_code) - 1); } - printf_xml(" http=\"%s\"", buffer + 9); + } else { // Output HTTP code... - printf(" "); + strncpy(http_code, " ", sizeof(http_code) - 1); } } } - printf_xml(" sslversion=\"%s\"", cleanSslMethod); -#ifndef OPENSSL_NO_SSL2 - if (strcmp(cleanSslMethod, "SSLv2") == 0) - { - printf("%sSSLv2%s ", COL_RED, RESET); - } - else -#endif -#ifndef OPENSSL_NO_SSL3 - if (strcmp(cleanSslMethod, "SSLv3") == 0) - { - printf("%sSSLv3%s ", COL_RED, RESET); - } - else -#endif - if (strcmp(cleanSslMethod, "TLSv1.0") == 0) - { - printf("%sTLSv1.0%s ", COL_YELLOW, RESET); - } -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - else - { - printf("%s ", cleanSslMethod); - } -#endif - if (cipherbits < 10) - tempInt = 2; - else if (cipherbits < 100) - tempInt = 1; - else - tempInt = 0; - if (cipherbits == 0) - { - printf("%s%d%s bits ", COL_RED_BG, cipherbits, RESET); - } - else if (cipherbits >= 112) - { - printf("%s%d%s bits ", COL_GREEN, cipherbits, RESET); - } - else if (cipherbits > 56) - { - printf("%s%d%s bits ", COL_YELLOW, cipherbits, RESET); - } - else - { - printf("%s%d%s bits ", COL_RED, cipherbits, RESET); - } - while (tempInt != 0) - { - tempInt--; - printf(" "); - } - - sprintf(hexCipherId, "0x%X", cipherid); - if (options->showCipherIds == true) - { - printf("%8s ", hexCipherId); - } + ciphername = SSL_CIPHER_get_name(sslCipherPointer); - printf_xml(" bits=\"%d\" cipher=\"%s\" id=\"%s\"", cipherbits, sslCipherPointer->name, hexCipherId); - if (strstr(sslCipherPointer->name, "NULL")) - { - printf("%s%-29s%s", COL_RED_BG, sslCipherPointer->name, RESET); - strength = "null"; - } - else if (strstr(sslCipherPointer->name, "ADH") || strstr(sslCipherPointer->name, "AECDH")) - { - printf("%s%-29s%s", COL_PURPLE, sslCipherPointer->name, RESET); - strength = "anonymous"; - } - else if (strstr(sslCipherPointer->name, "EXP")) - { - printf("%s%-29s%s", COL_RED, sslCipherPointer->name, RESET); - strength = "weak"; - } - else if (strstr(sslCipherPointer->name, "RC4") || strstr(sslCipherPointer->name, "DES")) - { - printf("%s%-29s%s", COL_YELLOW, sslCipherPointer->name, RESET); - strength = "medium"; - } - else if ((strstr(sslCipherPointer->name, "CHACHA20") || (strstr(sslCipherPointer->name, "GCM"))) - && strstr(sslCipherPointer->name, "DHE")) - { - printf("%s%-29s%s", COL_GREEN, sslCipherPointer->name, RESET); - strength = "strong"; - } - else - { - printf("%-29s", sslCipherPointer->name); - strength = "acceptable"; - } + // Timing + if (options->showTimes) { + struct timeval tval_end = {0}, tval_elapsed = {0}; - if (options->cipher_details == true) - { - ssl_print_tmp_key(options, ssl); - } - // Timing - if (options->showTimes) - { - int msec; - gettimeofday(&tval_end, NULL); - timersub(&tval_end, &tval_start, &tval_elapsed); - msec = tval_elapsed.tv_sec * 1000 + (int)tval_elapsed.tv_usec/1000; - printf("%s %dms%s", COL_GREY, msec, RESET); - printf_xml(" time=\"%d\"", msec); - } + gettimeofday(&tval_end, NULL); + timersub(&tval_end, &tval_start, &tval_elapsed); + milliseconds_elapsed = tval_elapsed.tv_sec * 1000 + (int)tval_elapsed.tv_usec / 1000; + } - printf("\n"); - printf_xml(" strength=\"%s\" />\n", strength); + outputCipher(options, ssl, cleanSslMethod, cipherid, ciphername, cipherbits, (cipherStatus == 1), milliseconds_elapsed, http_code); // Disconnect SSL over socket if (cipherStatus == 1) { - strncat(options->cipherstring, ":!", 2); - strncat(options->cipherstring, SSL_get_cipher_name(ssl), strlen(SSL_get_cipher_name(ssl))); + const char *usedcipher = SSL_get_cipher_name(ssl); + if(sslMethod==TLSv1_3_client_method()) + { // Remove cipher from TLSv1.3 list + cipherRemove(options->cipherstring, usedcipher); + } + else + { + strncat(options->cipherstring, ":!", 2); + strncat(options->cipherstring, usedcipher, strlen(usedcipher)); + } SSL_shutdown(ssl); } // Free SSL object - SSL_free(ssl); + FREE_SSL(ssl); } else { @@ -1778,7 +1816,7 @@ int testCipher(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) } // Disconnect from host - close(socketDescriptor); + CLOSE(socketDescriptor); } // Could not connect @@ -1793,7 +1831,7 @@ int checkCertificateProtocol(struct sslCheckOptions *options, const SSL_METHOD * { int status = true; // Setup Context Object... - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { // SSL implementation bugs/workaround @@ -1834,17 +1872,19 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho EVP_PKEY *publicKey = NULL; char certAlgorithm[80]; X509_EXTENSION *extension = NULL; + const X509_ALGOR *palg = NULL; + const ASN1_OBJECT *paobj = NULL; // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { - if (SSL_CTX_set_cipher_list(options->ctx, "ALL:COMPLEMENTOFALL") != 0) + if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) @@ -1853,7 +1893,7 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho if (status == true) { // Create SSL object... - ssl = SSL_new(options->ctx); + ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO @@ -1914,27 +1954,27 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SIGNAME)) { printf("Signature Algorithm: "); - i2t_ASN1_OBJECT(certAlgorithm, sizeof(certAlgorithm), x509Cert->cert_info->signature->algorithm); + X509_get0_signature(NULL, &palg, x509Cert); + X509_ALGOR_get0(&paobj, NULL, NULL, palg); + OBJ_obj2txt(certAlgorithm, sizeof(certAlgorithm), paobj, 0); strtok(certAlgorithm, "\n"); if (strstr(certAlgorithm, "md5") || strstr(certAlgorithm, "sha1")) { - printf_xml(" "); printf("%s%s%s\n", COL_RED, certAlgorithm, RESET); } else if (strstr(certAlgorithm, "sha512") || strstr(certAlgorithm, "sha256")) { - printf_xml(" "); printf("%s%s%s\n", COL_GREEN, certAlgorithm, RESET); } else { - printf_xml(" "); printf("%s\n", certAlgorithm); } if (options->xmlOutput) { - i2a_ASN1_OBJECT(fileBIO, x509Cert->cert_info->signature->algorithm); + printf_xml(" "); + X509_signature_print(fileBIO, palg, NULL); printf_xml("\n"); } } @@ -1950,28 +1990,26 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho } else { - switch (publicKey->type) + keyBits=EVP_PKEY_bits(publicKey); + switch (EVP_PKEY_id(publicKey)) { case EVP_PKEY_RSA: - if (publicKey->pkey.rsa) + if (EVP_PKEY_get1_RSA(publicKey)!=NULL) { - keyBits = BN_num_bits(publicKey->pkey.rsa->n); - printf_xml(" pkey.rsa->n)); if (keyBits < 2048 ) { printf("RSA Key Strength: %s%d%s\n", COL_RED, keyBits, RESET); - printf_xml("strength=\"weak\" />\n"); } else if (keyBits >= 4096 ) { printf("RSA Key Strength: %s%d%s\n", COL_GREEN, keyBits, RESET); - printf_xml("strength=\"strong\" />\n"); } else { printf("RSA Key Strength: %d\n", keyBits); - printf_xml("strength=\"acceptable\" />\n"); } + + printf_xml(" \n", keyBits); } else { @@ -1980,7 +2018,7 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho printf("\n"); break; case EVP_PKEY_DSA: - if (publicKey->pkey.dsa) + if (EVP_PKEY_get1_DSA(publicKey)!=NULL) { // TODO - display key strength printf_xml(" \n"); @@ -1992,7 +2030,7 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho } break; case EVP_PKEY_EC: - if (publicKey->pkey.ec) + if (EVP_PKEY_get1_EC_KEY(publicKey)) { // TODO - display key strength printf_xml(" \n"); @@ -2048,23 +2086,23 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho // Get certificate altnames if supported if (!(X509_FLAG_COMPAT & X509_FLAG_NO_EXTENSIONS)) { - if (sk_X509_EXTENSION_num(x509Cert->cert_info->extensions) > 0) + if (sk_X509_EXTENSION_num(X509_get0_extensions(x509Cert)) > 0) { cnindex = X509_get_ext_by_NID (x509Cert, NID_subject_alt_name, -1); if (cnindex != -1) { - extension = X509v3_get_ext(x509Cert->cert_info->extensions,cnindex); + extension = X509v3_get_ext(X509_get0_extensions(x509Cert),cnindex); printf("Altnames: "); if (!X509V3_EXT_print(stdoutBIO, extension, X509_FLAG_COMPAT, 0)) { - M_ASN1_OCTET_STRING_print(stdoutBIO, extension->value); + ASN1_STRING_print(stdoutBIO, X509_EXTENSION_get_data(extension)); } if (options->xmlOutput) { printf_xml(" value); + ASN1_STRING_print(fileBIO, X509_EXTENSION_get_data(extension)); } printf_xml("]]>\n"); printf("\n"); @@ -2186,7 +2224,7 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho SSL_shutdown(ssl); } // Free SSL object - SSL_free(ssl); + FREE_SSL(ssl); } else { @@ -2202,7 +2240,7 @@ int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMetho } // Free CTX Object - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); } // Error Creating Context Object else @@ -2253,16 +2291,19 @@ int ocspRequest(struct sslCheckOptions *options) sslMethod = TLSv1_2_method(); } #endif + else if( options->sslVersion == tls_v13) { + printf_verbose("sslMethod = TLSv1_3_method()"); + sslMethod = TLSv1_3_method(); + } else { - printf_verbose("sslMethod = TLSv1_method()\n"); - printf_verbose("If server doesn't support TLSv1.0, manually specify TLS version\n"); - sslMethod = TLSv1_method(); + printf_verbose("sslMethod = TLS_method()\n"); + sslMethod = TLS_method(); } - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { - if (SSL_CTX_set_cipher_list(options->ctx, "ALL:COMPLEMENTOFALL") != 0) + if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) @@ -2271,7 +2312,7 @@ int ocspRequest(struct sslCheckOptions *options) if (status == true) { // Create SSL object... - ssl = SSL_new(options->ctx); + ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO @@ -2326,7 +2367,7 @@ int ocspRequest(struct sslCheckOptions *options) printf("Most likely cause is server not supporting %s, try manually specifying version\n", printableSslMethod(sslMethod)); } // Free SSL object - SSL_free(ssl); + FREE_SSL(ssl); } else { @@ -2342,7 +2383,7 @@ int ocspRequest(struct sslCheckOptions *options) } // Free CTX Object - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); } // Error Creating Context Object else @@ -2362,27 +2403,13 @@ int ocspRequest(struct sslCheckOptions *options) return status; } -static int ocsp_resp_cb(SSL *s, void *arg) -{ - const unsigned char *p; - int len; - OCSP_RESPONSE *rsp; - len = SSL_get_tlsext_status_ocsp_resp(s, &p); - if (!p) { - printf("No OCSP response sent\n\n"); - return 1; - } - rsp = d2i_OCSP_RESPONSE(NULL, &p, len); - if (!rsp){ - printf("OCSP response parse error\n"); - return 0; - } - - BIO *bio_out; - bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); - +static int ocsp_resp_cb(SSL *s, void *unused) { + const unsigned char *p = NULL; + int len = 0; + OCSP_RESPONSE *o = NULL; + BIO *bp = BIO_new_fp(stdout, BIO_NOCLOSE); int i = 0; - long l; + long l = 0; OCSP_CERTID *cid = NULL; OCSP_BASICRESP *br = NULL; OCSP_RESPID *rid = NULL; @@ -2390,95 +2417,145 @@ static int ocsp_resp_cb(SSL *s, void *arg) OCSP_CERTSTATUS *cst = NULL; OCSP_REVOKEDINFO *rev = NULL; OCSP_SINGLERESP *single = NULL; - OCSP_RESPBYTES *rb = rsp->responseBytes; - - //Pretty print response status - l = ASN1_ENUMERATED_get(rsp->responseStatus); - if (BIO_printf(bio_out, "OCSP Response Status: %s (0x%lx)\n", - OCSP_response_status_str(l), l) <= 0) - goto err; - - //Check for null response bytes - if (rb == NULL) - return 1; - i = ASN1_STRING_length(rb->response); - if ((br = OCSP_response_get1_basic(rsp)) == NULL) - goto err; - rd = br->tbsResponseData; - l = ASN1_INTEGER_get(rd->version); - - //Pretty print responder id - if(BIO_puts(bio_out, "Responder Id: ") <= 0) - goto err; - rid = rd->responderId; - switch (rid->type){ - case V_OCSP_RESPID_NAME: - X509_NAME_print_ex(bio_out, rid->value.byName, 0, XN_FLAG_ONELINE); - break; - case V_OCSP_RESPID_KEY: - i2a_ASN1_STRING(bio_out, rid->value.byKey, V_ASN1_OCTET_STRING); - break; - } + OCSP_RESPBYTES *rb = NULL; - if(BIO_printf(bio_out, "\nProduced At: ") <= 0) - goto err; - if (!ASN1_GENERALIZEDTIME_print(bio_out, rd->producedAt)) - goto err; - if (BIO_printf(bio_out, "\nResponses:\n") <= 0) - goto err; - for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) - { - if (!sk_OCSP_SINGLERESP_value(rd->responses, i)) + + len = SSL_get_tlsext_status_ocsp_resp(s, &p); + if (p == NULL) { + BIO_puts(bp, "No OCSP response recieved.\n\n"); + goto err; + } + + o = d2i_OCSP_RESPONSE(NULL, &p, len); + if (o == NULL) { + BIO_puts(bp, "OCSP response parse error\n"); + BIO_dump_indent(bp, (char *)p, len, 4); + goto err; + } + + rb = o->responseBytes; + l = ASN1_ENUMERATED_get(o->responseStatus); + if (BIO_printf(bp, "OCSP Response Status: %s (0x%lx)\n", + OCSP_response_status_str(l), l) <= 0) + goto err; + if (rb == NULL) + return 1; + if (BIO_puts(bp, "Response Type: ") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, rb->responseType) <= 0) + goto err; + if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) { + BIO_puts(bp, " (unknown response type)\n"); + return 1; + } + + if ((br = OCSP_response_get1_basic(o)) == NULL) + goto err; + rd = &br->tbsResponseData; + l = ASN1_INTEGER_get(rd->version); + if (BIO_printf(bp, "\nVersion: %lu (0x%lx)\n", l + 1, l) <= 0) + goto err; + if (BIO_puts(bp, "Responder Id: ") <= 0) + goto err; + + rid = &rd->responderId; + switch (rid->type) { + case V_OCSP_RESPID_NAME: + X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE); + break; + case V_OCSP_RESPID_KEY: + i2a_ASN1_STRING(bp, rid->value.byKey, 0); + break; + } + + if (BIO_printf(bp, "\nProduced At: ") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt)) + goto err; + if (BIO_printf(bp, "\nResponses:\n") <= 0) + goto err; + for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) { + if (!sk_OCSP_SINGLERESP_value(rd->responses, i)) continue; single = sk_OCSP_SINGLERESP_value(rd->responses, i); cid = single->certId; - if (ocsp_certid_print(bio_out, cid, 4) <= 0) + if (ocsp_certid_print(bp, cid, 4) <= 0) goto err; cst = single->certStatus; - if (cst->type == V_OCSP_CERTSTATUS_GOOD) - { - if (BIO_printf(bio_out, "Cert Status: %s%s%s\n\n", - COL_GREEN, OCSP_cert_status_str(cst->type), RESET) <= 0) + if (BIO_puts(bp, " Cert Status: ") <= 0) + goto err; + if (cst->type == V_OCSP_CERTSTATUS_GOOD) { + if (BIO_printf(bp, "%s%s%s", COL_GREEN, OCSP_cert_status_str(cst->type), RESET) <= 0) goto err; - } - else if (cst->type == V_OCSP_CERTSTATUS_UNKNOWN) - { - if (BIO_printf(bio_out, "Cert Status: %s%s%s\n\n", - COL_YELLOW, OCSP_cert_status_str(cst->type), RESET) <= 0) + } else if (cst->type == V_OCSP_CERTSTATUS_REVOKED) { + if (BIO_printf(bp, "%s%s%s", COL_RED, OCSP_cert_status_str(cst->type), RESET) <= 0) goto err; - } - else - { rev = cst->value.revoked; - if (BIO_printf(bio_out, "\nRevocation Time: \n\n") <= 0) + if (BIO_printf(bp, "\n Revocation Time: ") <= 0) goto err; - if (!ASN1_GENERALIZEDTIME_print(bio_out, rev->revocationTime)) + if (!ASN1_GENERALIZEDTIME_print(bp, rev->revocationTime)) goto err; if (rev->revocationReason) { l = ASN1_ENUMERATED_get(rev->revocationReason); - if (BIO_printf(bio_out, - "\nRevocation Reason: %s (0x%lx)\n\n", + if (BIO_printf(bp, + "\n Revocation Reason: %s (0x%lx)", OCSP_crl_reason_str(l), l) <= 0) goto err; } - } + } else { + if (BIO_printf(bp, "%s%s%s", COL_YELLOW, OCSP_cert_status_str(cst->type), RESET) <= 0) + goto err; } - err: - OCSP_RESPONSE_free(rsp); - return 1; - + if (BIO_printf(bp, "\n This Update: ") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate)) + goto err; + if (single->nextUpdate) { + if (BIO_printf(bp, "\n Next Update: ") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, single->nextUpdate)) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + + if (!X509V3_extensions_print(bp, + "Response Single Extensions", + single->singleExtensions, 0, 4)) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + /* + if (!X509V3_extensions_print(bp, "Response Extensions", + rd->responseExtensions, 0, 4)) + goto err; + if (X509_signature_print(bp, &br->signatureAlgorithm, br->signature) <= 0) + goto err; + + for (i = 0; i < sk_X509_num(br->certs); i++) { + X509_print(bp, sk_X509_value(br->certs, i)); + PEM_write_bio_X509(bp, sk_X509_value(br->certs, i)); + } + */ + err: + if (o != NULL) { OCSP_RESPONSE_free(o); o = NULL; } + BIO_free(bp); + return 1; } int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent) { + BIO_printf(bp, "%*sCertificate ID:\n", indent, ""); + indent += 2; BIO_printf(bp, "%*sHash Algorithm: ", indent, ""); - i2a_ASN1_OBJECT(bp, a->hashAlgorithm->algorithm); + i2a_ASN1_OBJECT(bp, a->hashAlgorithm.algorithm); BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, ""); - i2a_ASN1_STRING(bp, a->issuerNameHash, V_ASN1_OCTET_STRING); + i2a_ASN1_STRING(bp, &a->issuerNameHash, 0); BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, ""); - i2a_ASN1_STRING(bp, a->issuerKeyHash, V_ASN1_OCTET_STRING); + i2a_ASN1_STRING(bp, &a->issuerKeyHash, 0); BIO_printf(bp, "\n%*sSerial Number: ", indent, ""); - i2a_ASN1_INTEGER(bp, a->serialNumber); + i2a_ASN1_INTEGER(bp, &a->serialNumber); BIO_printf(bp, "\n"); return 1; } @@ -2524,16 +2601,19 @@ int showCertificate(struct sslCheckOptions *options) printf_verbose("sslMethod = TLSv1_2_method()"); sslMethod = TLSv1_2_method(); } + else if( options->sslVersion == tls_v13) { + printf_verbose("sslMethod = TLSv1_3_method()"); + sslMethod = TLSv1_3_method(); + } #endif else { - printf_verbose("sslMethod = TLSv1_method()\n"); - printf_verbose("If server doesn't support TLSv1.0, manually specify TLS version\n"); - sslMethod = TLSv1_method(); + printf_verbose("sslMethod = TLS_method()\n"); + sslMethod = TLS_method(); } - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { - if (SSL_CTX_set_cipher_list(options->ctx, "ALL:COMPLEMENTOFALL") != 0) + if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) @@ -2542,7 +2622,7 @@ int showCertificate(struct sslCheckOptions *options) if (status == true) { // Create SSL object... - ssl = SSL_new(options->ctx); + ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO @@ -2600,6 +2680,8 @@ int showCertificate(struct sslCheckOptions *options) //SSL_set_verify(ssl, SSL_VERIFY_NONE|SSL_VERIFY_CLIENT_ONCE, NULL); + //X509_print_ex(bp, x509Cert, 0, 0); + // Cert Version if (!(X509_FLAG_COMPAT & X509_FLAG_NO_VERSION)) { @@ -2683,13 +2765,15 @@ int showCertificate(struct sslCheckOptions *options) // Signature Algo... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SIGNAME)) { - printf(" Signature Algorithm: "); - i2a_ASN1_OBJECT(stdoutBIO, x509Cert->cert_info->signature->algorithm); + X509_signature_print(stdoutBIO, X509_get0_tbs_sigalg(x509Cert), NULL); +/* printf(" Signature Algorithm: "); + i2a_ASN1_OBJECT(stdoutBIO, X509_get0_tbs_sigalg(x509Cert)); printf("\n"); +*/ if (options->xmlOutput) { printf_xml(" "); - i2a_ASN1_OBJECT(fileBIO, x509Cert->cert_info->signature->algorithm); + X509_signature_print(fileBIO, X509_get0_tbs_sigalg(x509Cert), NULL); printf_xml("\n"); } } @@ -2736,12 +2820,13 @@ int showCertificate(struct sslCheckOptions *options) if (!(X509_FLAG_COMPAT & X509_FLAG_NO_PUBKEY)) { printf(" Public Key Algorithm: "); - i2a_ASN1_OBJECT(stdoutBIO, x509Cert->cert_info->key->algor->algorithm); + ASN1_OBJECT *xpoid = NULL; + i2a_ASN1_OBJECT(stdoutBIO, xpoid); printf("\n"); if (options->xmlOutput) { printf_xml(" "); - i2a_ASN1_OBJECT(fileBIO, x509Cert->cert_info->key->algor->algorithm); + i2a_ASN1_OBJECT(fileBIO, xpoid); printf_xml("\n"); } @@ -2754,17 +2839,17 @@ int showCertificate(struct sslCheckOptions *options) } else { - switch (publicKey->type) + switch (EVP_PKEY_id(publicKey)) { case EVP_PKEY_RSA: - if (publicKey->pkey.rsa) + if (EVP_PKEY_get1_RSA(publicKey)!=NULL) { - printf(" RSA Public Key: (%d bit)\n", BN_num_bits(publicKey->pkey.rsa->n)); - printf_xml(" \n", BN_num_bits(publicKey->pkey.rsa->n)); - RSA_print(stdoutBIO, publicKey->pkey.rsa, 6); + printf(" RSA Public Key: (%d bit)\n", EVP_PKEY_bits(publicKey)); + printf_xml(" \n", EVP_PKEY_bits(publicKey)); + RSA_print(stdoutBIO, EVP_PKEY_get1_RSA(publicKey), 6); if (options->xmlOutput) { - RSA_print(fileBIO, publicKey->pkey.rsa, 4); + RSA_print(fileBIO, EVP_PKEY_get1_RSA(publicKey), 4); printf_xml(" \n"); } } @@ -2774,14 +2859,14 @@ int showCertificate(struct sslCheckOptions *options) } break; case EVP_PKEY_DSA: - if (publicKey->pkey.dsa) + if (EVP_PKEY_get1_DSA(publicKey)!=NULL) { printf(" DSA Public Key:\n"); printf_xml(" \n"); - DSA_print(stdoutBIO, publicKey->pkey.dsa, 6); + DSA_print(stdoutBIO, EVP_PKEY_get1_DSA(publicKey), 6); if (options->xmlOutput) { - DSA_print(fileBIO, publicKey->pkey.dsa, 4); + DSA_print(fileBIO, EVP_PKEY_get1_DSA(publicKey), 4); printf_xml(" \n"); } } @@ -2791,14 +2876,14 @@ int showCertificate(struct sslCheckOptions *options) } break; case EVP_PKEY_EC: - if (publicKey->pkey.ec) + if (EVP_PKEY_get1_EC_KEY(publicKey)!=NULL) { printf(" EC Public Key:\n"); printf_xml(" \n"); - EC_KEY_print(stdoutBIO, publicKey->pkey.ec, 6); + EC_KEY_print(stdoutBIO, EVP_PKEY_get1_EC_KEY(publicKey), 6); if (options->xmlOutput) { - EC_KEY_print(fileBIO, publicKey->pkey.ec, 4); + EC_KEY_print(fileBIO, EVP_PKEY_get1_EC_KEY(publicKey), 4); printf_xml(" \n"); } } @@ -2820,14 +2905,14 @@ int showCertificate(struct sslCheckOptions *options) // X509 v3... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_EXTENSIONS)) { - if (sk_X509_EXTENSION_num(x509Cert->cert_info->extensions) > 0) + if (sk_X509_EXTENSION_num(X509_get0_extensions(x509Cert)) > 0) { printf(" X509v3 Extensions:\n"); printf_xml(" \n"); - for (tempInt = 0; tempInt < sk_X509_EXTENSION_num(x509Cert->cert_info->extensions); tempInt++) + for (tempInt = 0; tempInt < sk_X509_EXTENSION_num(X509_get0_extensions(x509Cert)); tempInt++) { // Get Extension... - extension = sk_X509_EXTENSION_value(x509Cert->cert_info->extensions, tempInt); + extension = sk_X509_EXTENSION_value(X509_get0_extensions(x509Cert), tempInt); // Print Extension name... printf(" "); @@ -2846,12 +2931,12 @@ int showCertificate(struct sslCheckOptions *options) if (!X509V3_EXT_print(stdoutBIO, extension, X509_FLAG_COMPAT, 8)) { printf(" "); - M_ASN1_OCTET_STRING_print(stdoutBIO, extension->value); + ASN1_STRING_print(stdoutBIO, X509_EXTENSION_get_data(extension)); } if (options->xmlOutput) { if (!X509V3_EXT_print(fileBIO, extension, X509_FLAG_COMPAT, 0)) - M_ASN1_OCTET_STRING_print(fileBIO, extension->value); + ASN1_STRING_print(stdoutBIO, X509_EXTENSION_get_data(extension)); printf_xml("]]>\n"); } printf("\n"); @@ -2892,7 +2977,7 @@ int showCertificate(struct sslCheckOptions *options) } // Free SSL object - SSL_free(ssl); + FREE_SSL(ssl); } else { @@ -2908,7 +2993,7 @@ int showCertificate(struct sslCheckOptions *options) } // Free CTX Object - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); } // Error Creating Context Object @@ -2966,16 +3051,19 @@ int showTrustedCAs(struct sslCheckOptions *options) printf_verbose("sslMethod = TLSv1_2_method()"); sslMethod = TLSv1_2_method(); } + else if( options->sslVersion == tls_v13) { + printf_verbose("sslMethod = TLSv1_3_method()"); + sslMethod = TLSv1_3_method(); + } #endif else { - printf_verbose("sslMethod = TLSv1_method()\n"); - printf_verbose("If server doesn't support TLSv1.0, manually specify TLS version\n"); - sslMethod = TLSv1_method(); + printf_verbose("sslMethod = TLS_method()\n"); + sslMethod = TLS_method(); } - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { - if (SSL_CTX_set_cipher_list(options->ctx, "ALL:COMPLEMENTOFALL") != 0) + if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) @@ -2984,7 +3072,7 @@ int showTrustedCAs(struct sslCheckOptions *options) if (status == true) { // Create SSL object... - ssl = SSL_new(options->ctx); + ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO @@ -3057,7 +3145,7 @@ int showTrustedCAs(struct sslCheckOptions *options) } // Free SSL object - SSL_free(ssl); + FREE_SSL(ssl); } else { @@ -3073,7 +3161,7 @@ int showTrustedCAs(struct sslCheckOptions *options) } // Free CTX Object - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); } // Error Creating Context Object @@ -3165,22 +3253,29 @@ int testProtocolCiphers(struct sslCheckOptions *options, const SSL_METHOD *sslMe { int status; status = true; - strncpy(options->cipherstring, "ALL:eNULL", 10); + + if (sslMethod == TLSv1_3_client_method()) + strncpy(options->cipherstring, TLSV13_CIPHERSUITES, sizeof(options->cipherstring)); + else + strncpy(options->cipherstring, CIPHERSUITE_LIST_ALL, sizeof(options->cipherstring)); // Loop until the server won't accept any more ciphers while (status == true) { // Setup Context Object... - options->ctx = SSL_CTX_new(sslMethod); + options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { - // SSL implementation bugs/workaround if (options->sslbugs) SSL_CTX_set_options(options->ctx, SSL_OP_ALL | 0); else SSL_CTX_set_options(options->ctx, 0); + // minimal protocol version + if (sslMethod == TLSv1_3_client_method()) + SSL_CTX_set_min_proto_version(options->ctx, TLS1_3_VERSION); + // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); @@ -3190,7 +3285,7 @@ int testProtocolCiphers(struct sslCheckOptions *options, const SSL_METHOD *sslMe status = testCipher(options, sslMethod); // Free CTX Object - SSL_CTX_free(options->ctx); + FREE_CTX(options->ctx); } // Error Creating Context Object @@ -3200,6 +3295,17 @@ int testProtocolCiphers(struct sslCheckOptions *options, const SSL_METHOD *sslMe return false; } } + + /* Test the missing ciphersuites. */ + if (sslMethod != TLSv1_3_client_method()) { + int tls_version = TLSv1_0; + if (sslMethod == TLSv1_1_client_method()) + tls_version = TLSv1_1; + else if (sslMethod == TLSv1_2_client_method()) + tls_version = TLSv1_2; + + testMissingCiphers(options, tls_version); + } return true; } @@ -3222,31 +3328,96 @@ int testHost(struct sslCheckOptions *options) printf("Testing SSL server %s%s%s on port %s%d%s using SNI name %s%s%s\n\n", COL_GREEN, options->host, RESET, COL_GREEN, options->port, RESET, COL_GREEN, options->sniname, RESET); + printf(" %sSSL/TLS Protocols:%s\n", COL_BLUE, RESET); + + // Check if SSLv2 is enabled. + if ((options->sslVersion == ssl_all) || (options->sslVersion == ssl_v2)) { + if (runSSLv2Test(options)) { + printf("SSLv2 %senabled%s\n", COL_RED, RESET); + printf_xml(" \n"); + } else { + printf("SSLv2 %sdisabled%s\n", COL_GREEN, RESET); + printf_xml(" \n"); + } + } + + // Check if SSLv3 is enabled. + if ((options->sslVersion == ssl_all) || (options->sslVersion == ssl_v3)) { + if (runSSLv3Test(options)) { + printf("SSLv3 %senabled%s\n", COL_RED, RESET); + printf_xml(" \n"); + } else { + printf("SSLv3 %sdisabled%s\n", COL_GREEN, RESET); + printf_xml(" \n"); + } + } + + /* Test if TLSv1.0 through TLSv1.3 is supported. This allows us to skip unnecessary tests later. Print status of each protocol when verbose flag is set. */ + if ((options->sslVersion == ssl_all) || (options->sslVersion == tls_all) || (options->sslVersion == tls_v10)) { + if ((options->tls10_supported = checkIfTLSVersionIsSupported(options, TLSv1_0))) { + printf("TLSv1.0 %senabled%s\n", COL_YELLOW, RESET); + printf_xml(" \n"); + } else { + printf("TLSv1.0 %sdisabled%s\n", COL_GREEN, RESET); + printf_xml(" \n"); + } + } + + if ((options->sslVersion == ssl_all) || (options->sslVersion == tls_all) || (options->sslVersion == tls_v11)) { + if ((options->tls11_supported = checkIfTLSVersionIsSupported(options, TLSv1_1))) { + printf("TLSv1.1 enabled\n"); + printf_xml(" \n"); + } else { + printf("TLSv1.1 disabled\n"); + printf_xml(" \n"); + } + } + + if ((options->sslVersion == ssl_all) || (options->sslVersion == tls_all) || (options->sslVersion == tls_v12)) { + if ((options->tls12_supported = checkIfTLSVersionIsSupported(options, TLSv1_2))) { + printf("TLSv1.2 enabled\n"); + printf_xml(" \n"); + } else { + printf("TLSv1.2 not enabled\n"); + printf_xml(" \n"); + } + } + + if ((options->sslVersion == ssl_all) || (options->sslVersion == tls_all) || (options->sslVersion == tls_v13)) { + if ((options->tls13_supported = checkIfTLSVersionIsSupported(options, TLSv1_3))) { + printf("TLSv1.3 %senabled%s\n", COL_GREEN, RESET); + printf_xml(" \n"); + } else { + printf("TLSv1.3 not enabled\n"); + printf_xml(" \n"); + } + } + printf("\n"); + if (options->showClientCiphers == true) { // Build a list of ciphers... switch (options->sslVersion) { case ssl_all: + populateCipherList(options, TLSv1_3_client_method()); #if OPENSSL_VERSION_NUMBER >= 0x10001000L populateCipherList(options, TLSv1_2_client_method()); populateCipherList(options, TLSv1_1_client_method()); #endif populateCipherList(options, TLSv1_client_method()); -#ifndef OPENSSL_NO_SSL3 - populateCipherList(options, SSLv3_client_method()); -#endif -#ifndef OPENSSL_NO_SSL2 - populateCipherList(options, SSLv2_client_method()); -#endif break; case tls_all: + populateCipherList(options, TLSv1_3_client_method()); #if OPENSSL_VERSION_NUMBER >= 0x10001000L populateCipherList(options, TLSv1_2_client_method()); populateCipherList(options, TLSv1_1_client_method()); #endif populateCipherList(options, TLSv1_client_method()); break; + case tls_v13: + populateCipherList(options, TLSv1_3_client_method()); + break; #if OPENSSL_VERSION_NUMBER >= 0x10001000L case tls_v12: populateCipherList(options, TLSv1_2_client_method()); @@ -3258,26 +3429,21 @@ int testHost(struct sslCheckOptions *options) case tls_v10: populateCipherList(options, TLSv1_client_method()); break; -#ifndef OPENSSL_NO_SSL3 - case ssl_v3: - populateCipherList(options, SSLv3_client_method()); - break; -#endif -#ifndef OPENSSL_NO_SSL2 - case ssl_v2: - populateCipherList(options, SSLv2_client_method()); - break; -#endif } - printf("\n %sSupported Client Cipher(s):%s\n", COL_BLUE, RESET); + printf("\n %sOpenSSL-Supported Client Cipher(s):%s\n", COL_BLUE, RESET); sslCipherPointer = options->ciphers; while ((sslCipherPointer != 0) && (status == true)) { printf(" %s\n",sslCipherPointer->name); - printf_xml(" \n", sslCipherPointer->name); + printf_xml(" \n", sslCipherPointer->name); sslCipherPointer = sslCipherPointer->next; } + printf("\n %sDirectly-Supported Client Cipher(s):%s\n", COL_BLUE, RESET); + for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { + printf(" %s\n", missing_ciphersuites[i].protocol_name); + printf_xml(" \n", missing_ciphersuites[i].protocol_name); + } printf("\n"); } if (status == true && options->fallback ) @@ -3306,20 +3472,25 @@ int testHost(struct sslCheckOptions *options) { printf(" %sHeartbleed:%s\n", COL_BLUE, RESET); #if OPENSSL_VERSION_NUMBER >= 0x10001000L - if( options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v12) + if ((options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v13) && options->tls13_supported) + { + printf("TLSv1.3 "); + status = testHeartbleed(options, TLSv1_3_client_method()); + } + if ((options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v12) && options->tls12_supported) { - printf("TLS 1.2 "); + printf("TLSv1.2 "); status = testHeartbleed(options, TLSv1_2_client_method()); } - if( options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v11) + if ((options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v11) && options->tls11_supported) { - printf("TLS 1.1 "); + printf("TLSv1.1 "); status = testHeartbleed(options, TLSv1_1_client_method()); } #endif - if( options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v10) + if ((options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v10) && options->tls10_supported) { - printf("TLS 1.0 "); + printf("TLSv1.0 "); status = testHeartbleed(options, TLSv1_client_method()); } if( options->sslVersion == ssl_v2 || options->sslVersion == ssl_v3) @@ -3338,7 +3509,6 @@ int testHost(struct sslCheckOptions *options) #endif } - if (options->ciphersuites) { // Test supported ciphers... @@ -3346,57 +3516,43 @@ int testHost(struct sslCheckOptions *options) switch (options->sslVersion) { case ssl_all: -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - if (status != false) - status = testProtocolCiphers(options, TLSv1_2_client_method()); - if (status != false) - status = testProtocolCiphers(options, TLSv1_1_client_method()); -#endif - if (status != false) - status = testProtocolCiphers(options, TLSv1_client_method()); -#ifndef OPENSSL_NO_SSL3 - if (status != false) - status = testProtocolCiphers(options, SSLv3_client_method()); -#endif -#ifndef OPENSSL_NO_SSL2 - if (status != false) - status = testProtocolCiphers(options, SSLv2_client_method()); -#endif - break; -#ifndef OPENSSL_NO_SSL2 - case ssl_v2: - status = testProtocolCiphers(options, SSLv2_client_method()); - break; -#endif -#ifndef OPENSSL_NO_SSL3 - case ssl_v3: - status = testProtocolCiphers(options, SSLv3_client_method()); - break; -#endif case tls_all: -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - if (status != false) + if ((status != false) && options->tls13_supported) + status = testProtocolCiphers(options, TLSv1_3_client_method()); + if ((status != false) && options->tls12_supported) status = testProtocolCiphers(options, TLSv1_2_client_method()); - if (status != false) + if ((status != false) && options->tls11_supported) status = testProtocolCiphers(options, TLSv1_1_client_method()); -#endif - if (status != false) + if ((status != false) && options->tls10_supported) status = testProtocolCiphers(options, TLSv1_client_method()); break; case tls_v10: - status = testProtocolCiphers(options, TLSv1_client_method()); + if ((status != false) && options->tls10_supported) + status = testProtocolCiphers(options, TLSv1_client_method()); break; -#if OPENSSL_VERSION_NUMBER >= 0x10001000L case tls_v11: - status = testProtocolCiphers(options, TLSv1_1_client_method()); + if ((status != false) && options->tls11_supported) + status = testProtocolCiphers(options, TLSv1_1_client_method()); break; case tls_v12: - status = testProtocolCiphers(options, TLSv1_2_client_method()); + if ((status != false) && options->tls12_supported) + status = testProtocolCiphers(options, TLSv1_2_client_method()); + break; + case tls_v13: + if ((status != false) && options->tls13_supported) + status = testProtocolCiphers(options, TLSv1_3_client_method()); break; -#endif } } + // Enumerate key exchange groups. + if (options->groups) + testSupportedGroups(options); + + // Enumerate signature algorithms. + if (options->signature_algorithms) + testSignatureAlgorithms(options); + // Print certificate if (status == true && options->showCertificate == true) { @@ -3406,24 +3562,16 @@ int testHost(struct sslCheckOptions *options) // Show weak certificate signing algorithm or key strength if (status == true && options->checkCertificate == true) { -#if OPENSSL_VERSION_NUMBER >= 0x10001000L if (status != false) - { + status = checkCertificateProtocol(options, TLSv1_3_client_method()); + if (status != false) status = checkCertificateProtocol(options, TLSv1_2_client_method()); - } if (status != false) status = checkCertificateProtocol(options, TLSv1_1_client_method()); -#endif if (status != false) status = checkCertificateProtocol(options, TLSv1_client_method()); -#ifndef OPENSSL_NO_SSL3 - if (status != false) - status = checkCertificateProtocol(options, SSLv3_client_method()); -#endif -#ifndef OPENSSL_NO_SSL2 if (status != false) - status = checkCertificateProtocol(options, SSLv2_client_method()); -#endif + printf("Certificate information cannot be enumerated through SSLv2 nor SSLv3.\n\n"); } // Print client auth trusted CAs @@ -3439,35 +3587,6 @@ int testHost(struct sslCheckOptions *options) return status; } -// Return a string description of an SSL error. -// It would be nice if there were a standard function for this... -const char *SSL_ERR_to_string (int sslerr) -{ - switch (sslerr) - { - // Values taken from openssl/ssl.h - case SSL_ERROR_NONE: - return "SSL_ERROR_NONE"; - case SSL_ERROR_SSL: - return "SSL_ERROR_SSL"; - case SSL_ERROR_WANT_READ: - return "SSL_ERROR_WANT_READ"; - case SSL_ERROR_WANT_WRITE: - return "SSL_ERROR_WANT_WRITE"; - case SSL_ERROR_WANT_X509_LOOKUP: - return "SSL_ERROR_WANT_X509_LOOKUP"; - case SSL_ERROR_SYSCALL: - return "SSL_ERROR_SYSCALL"; - case SSL_ERROR_ZERO_RETURN: - return "SSL_ERROR_ZERO_RETURN"; - case SSL_ERROR_WANT_CONNECT: - return "SSL_ERROR_WANT_CONNECT"; - case SSL_ERROR_WANT_ACCEPT: - return "SSL_ERROR_WANT_ACCEPT"; - default: - return "SSL_ERROR_UNKNOWN"; - } -} int main(int argc, char *argv[]) { @@ -3488,6 +3607,7 @@ int main(int argc, char *argv[]) int err; HANDLE hConsole; DWORD consoleMode; + unsigned int enable_colors; #endif // Init... @@ -3506,6 +3626,8 @@ int main(int argc, char *argv[]) options.fallback = true; options.compression = true; options.heartbleed = true; + options.groups = true; + options.signature_algorithms = true; options.starttls_ftp = false; options.starttls_imap = false; options.starttls_irc = false; @@ -3532,8 +3654,28 @@ int main(int argc, char *argv[]) #ifdef _WIN32 /* Attempt to enable console colors. This succeeds in Windows 10. For other * OSes, color is disabled. */ + enable_colors = 1; hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - if ((hConsole == INVALID_HANDLE_VALUE) || (!GetConsoleMode(hConsole, &consoleMode)) || (!SetConsoleMode(hConsole, consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))) { + + /* Cygwin's terminal is re-directed, so GetConsoleMode() fails on it. So we'll try to get a direct handle in that case. */ + if (!GetConsoleMode(hConsole, &consoleMode)) { + hConsole = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + /* Also, Cygwin appears to do full buffering of output, so the program seems to hang until its fully complete, then the output gets dumped all at once. To be more responsive, we'll force line buffering at 80 bytes (the default terminal width). */ + setvbuf(stdout, NULL, _IOLBF, 80); + + /* If we still can't get console information, then disable colors. */ + if (!GetConsoleMode(hConsole, &consoleMode)) + enable_colors = 0; + } + + /* Some terminals already have colors enabled, and somehow don't like being set. */ + if (enable_colors && ((consoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0)) { + if (!SetConsoleMode(hConsole, consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + enable_colors = 0; + } + + if (!enable_colors) { RESET = ""; COL_RED = ""; COL_YELLOW = ""; @@ -3661,6 +3803,14 @@ int main(int argc, char *argv[]) else if (strcmp("--no-heartbleed", argv[argLoop]) == 0) options.heartbleed = false; + // Should we check for key exchange groups? + else if (strcmp("--no-groups", argv[argLoop]) == 0) + options.groups = false; + + // Should we check for signature algorithms? + else if (strcmp("--no-sigs", argv[argLoop]) == 0) + options.signature_algorithms = false; + // StartTLS... FTP else if (strcmp("--starttls-ftp", argv[argLoop]) == 0) options.starttls_ftp = true; @@ -3696,16 +3846,14 @@ int main(int argc, char *argv[]) else if (strcmp("--starttls-psql", argv[argLoop]) == 0) options.starttls_psql = true; -#ifndef OPENSSL_NO_SSL2 // SSL v2 only... else if (strcmp("--ssl2", argv[argLoop]) == 0) options.sslVersion = ssl_v2; -#endif -#ifndef OPENSSL_NO_SSL3 + // SSL v3 only... else if (strcmp("--ssl3", argv[argLoop]) == 0) options.sslVersion = ssl_v3; -#endif + // TLS v1 only... else if (strcmp("--tls10", argv[argLoop]) == 0) options.sslVersion = tls_v10; @@ -3717,6 +3865,9 @@ int main(int argc, char *argv[]) // TLS v12 only... else if (strcmp("--tls12", argv[argLoop]) == 0) options.sslVersion = tls_v12; + // TLS v13 only... + else if (strcmp("--tls13", argv[argLoop]) == 0) + options.sslVersion = tls_v13; #endif // TLS (all versions)... else if (strcmp("--tlsall", argv[argLoop]) == 0) @@ -3890,19 +4041,14 @@ int main(int argc, char *argv[]) fprintf(options.xmlOutput, "\n\n", VERSION); } + // Build the list of ciphers missing from OpenSSL. + findMissingCiphers(); + switch (mode) { case mode_version: printf("%s\t\t%s\n\t\t%s\n%s", COL_BLUE, VERSION, SSLeay_version(SSLEAY_VERSION), RESET); -#ifdef OPENSSL_NO_SSL2 - printf("\t\t%sOpenSSL version does not support SSLv2%s\n", COL_RED, RESET); - printf("\t\t%sSSLv2 ciphers will not be detected%s\n", COL_RED, RESET); -#endif -#ifdef OPENSSL_NO_SSL3 - printf("\t\t%sOpenSSL version does not support SSLv3%s\n", COL_RED, RESET); - printf("\t\t%sSSLv3 ciphers will not be detected%s\n", COL_RED, RESET); -#endif #if OPENSSL_VERSION_NUMBER < 0x10001000L printf("\t\t%sOpenSSL version does not support TLSv1.1%s\n", COL_RED, RESET); printf("\t\t%sTLSv1.1 ciphers will not be detected%s\n", COL_RED, RESET); @@ -3919,10 +4065,6 @@ int main(int argc, char *argv[]) #ifdef OPENSSL_NO_SSL2 printf("%sOpenSSL version does not support SSLv2%s\n", COL_RED, RESET); printf("%sSSLv2 ciphers will not be detected%s\n\n", COL_RED, RESET); -#endif -#ifdef OPENSSL_NO_SSL3 - printf("%sOpenSSL version does not support SSLv3%s\n", COL_RED, RESET); - printf("%sSSLv3 ciphers will not be detected%s\n", COL_RED, RESET); #endif printf("%sCommand:%s\n", COL_BLUE, RESET); printf(" %s%s [Options] [host:port | host]%s\n\n", COL_GREEN, argv[0], RESET); @@ -3938,16 +4080,13 @@ int main(int argc, char *argv[]) printf(" %s--show-ciphers%s Show supported client ciphers\n", COL_GREEN, RESET); printf(" %s--show-cipher-ids%s Show cipher ids\n", COL_GREEN, RESET); printf(" %s--show-times%s Show handhake times in milliseconds\n", COL_GREEN, RESET); -#ifndef OPENSSL_NO_SSL2 printf(" %s--ssl2%s Only check SSLv2 ciphers\n", COL_GREEN, RESET); -#endif -#ifndef OPENSSL_NO_SSL3 printf(" %s--ssl3%s Only check SSLv3 ciphers\n", COL_GREEN, RESET); -#endif printf(" %s--tls10%s Only check TLSv1.0 ciphers\n", COL_GREEN, RESET); #if OPENSSL_VERSION_NUMBER >= 0x10001000L printf(" %s--tls11%s Only check TLSv1.1 ciphers\n", COL_GREEN, RESET); printf(" %s--tls12%s Only check TLSv1.2 ciphers\n", COL_GREEN, RESET); + printf(" %s--tls13%s Only check TLSv1.3 ciphers\n", COL_GREEN, RESET); #endif printf(" %s--tlsall%s Only check TLS ciphers (all versions)\n", COL_GREEN, RESET); printf(" %s--ocsp%s Request OCSP response from server\n", COL_GREEN, RESET); @@ -3962,6 +4101,8 @@ int main(int argc, char *argv[]) printf(" %s--no-renegotiation%s Do not check for TLS renegotiation\n", COL_GREEN, RESET); printf(" %s--no-compression%s Do not check for TLS compression (CRIME)\n", COL_GREEN, RESET); printf(" %s--no-heartbleed%s Do not check for OpenSSL Heartbleed (CVE-2014-0160)\n", COL_GREEN, RESET); + printf(" %s--no-groups%s Do not enumerate key exchange groups\n", COL_GREEN, RESET); + printf(" %s--no-sigs%s Do not enumerate signature algorithms\n", COL_GREEN, RESET); printf(" %s--starttls-ftp%s STARTTLS setup for FTP\n", COL_GREEN, RESET); printf(" %s--starttls-imap%s STARTTLS setup for IMAP\n", COL_GREEN, RESET); printf(" %s--starttls-irc%s STARTTLS setup for IRC\n", COL_GREEN, RESET); @@ -3996,14 +4137,6 @@ int main(int argc, char *argv[]) case mode_multiple: printf("Version: %s%s%s\n%s\n%s\n", COL_GREEN, VERSION, RESET, SSLeay_version(SSLEAY_VERSION), RESET); -#ifdef OPENSSL_NO_SSL2 - printf("%sOpenSSL version does not support SSLv2%s\n", COL_RED, RESET); - printf("%sSSLv2 ciphers will not be detected%s\n\n", COL_RED, RESET); -#endif -#ifdef OPENSSL_NO_SSL3 - printf("%sOpenSSL version does not support SSLv3%s\n", COL_RED, RESET); - printf("%sSSLv3 ciphers will not be detected%s\n", COL_RED, RESET); -#endif #if OPENSSL_VERSION_NUMBER < 0x10001000L printf("\t\t%sOpenSSL version does not support TLSv1.1%s\n", COL_RED, RESET); printf("\t\t%sTLSv1.1 ciphers will not be detected%s\n", COL_RED, RESET); @@ -4011,7 +4144,7 @@ int main(int argc, char *argv[]) printf("\t\t%sTLSv1.2 ciphers will not be detected%s\n", COL_RED, RESET); #endif - SSLeay_add_all_algorithms(); + //SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); // Do the testing... @@ -4102,6 +4235,1500 @@ int main(int argc, char *argv[]) return 0; } +int runSSLv2Test(struct sslCheckOptions *options) { + int ret = false, s = -1; + char sslv2_client_hello[] = { + 0x80, + 0x34, /* Length: 52 */ + 0x01, /* Handshake Message Type: Client Hello */ + 0x00, 0x02, /* Version: SSL 2.0 */ + 0x00, 0x1b, /* Cipher Spec Length: 27 */ + 0x00, 0x00, /* Session ID Length: 0 */ + 0x00, 0x10, /* Challenge Length: 16 */ + 0x05, 0x00, 0x80, /* SSL2_IDEA_128_CBC_WITH_MD5 */ + 0x03, 0x00, 0x80, /* SSL2_RC2_128_CBC_WITH_MD5 */ + 0x01, 0x00, 0x80, /* SSL2_RC4_128_WITH_MD5 */ + 0x07, 0x00, 0xc0, /* SSL2_DES_192_EDE3_CBC_WITH_MD5 */ + 0x08, 0x00, 0x80, /* SSL2_RC4_64_WITH_MD5 */ + 0x06, 0x00, 0x40, /* SSL2_DES_64_CBC_WITH_MD5 */ + 0x04, 0x00, 0x80, /* SSL2_RC2_128_CBC_EXPORT40_WITH_MD5 */ + 0x02, 0x00, 0x80, /* SSL2_RC4_128_EXPORT40_WITH_MD5 */ + 0x00, 0x00, 0x00, /* TLS_NULL_WITH_NULL_NULL */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f /* Challenge */ + }; + char response[8] = {0}; + + /* Create a socket to the target. */ + s = tcpConnect(options); + + /* If a connection could not be made, return false. */ + if (s == 0) + return false; + + /* Send the SSLv2 Client Hello packet. */ + if (send(s, sslv2_client_hello, sizeof(sslv2_client_hello), 0) <= 0) { + printf_error("send() failed: %s\n", strerror(errno)); + exit(1); + } + + /* Read a small amount of the response. */ + if (recv(s, response, sizeof(response), 0) != sizeof(response)) + goto done; /* Returns false. */ + + /* If the Handshake Message Type is Server Hello (0x04) and the Version is SSL 2.0 + * (0x00, 0x02), we confirm that this is SSL v2. */ + if ((response[2] == 0x04) && (response[5] == 0x00) && (response[6] == 0x02)) + ret = true; + + done: + close(s); + return ret; +} + +int runSSLv3Test(struct sslCheckOptions *options) { + int ret = false, s = -1; + uint32_t timestamp = 0; + unsigned char timestamp_bytes[4] = {0}; + char sslv3_client_hello_1[] = { + 0x16, /* Content Type: Handshake (22) */ + 0x03, 0x00, /* Version SSL 3.0 */ + 0x00, 0xe8, /* Length: 232 */ + 0x01, /* Handshake Type: Client Hello */ + 0x00, 0x00, 0xe4, /* Length: 228 */ + 0x03, 0x00, /* Version: SSL 3.0 */ + }; + + char sslv3_client_hello_2[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, /* Random bytes */ + 0x00, /* Session ID Length */ + 0x00, 0xbc, /* Cipher Suites Length: 188 */ + 0xc0, 0x14, /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */ + 0xc0, 0x0a, /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */ + 0x00, 0x39, /* TLS_DHE_RSA_WITH_AES_256_CBC_SHA */ + 0x00, 0x38, /* TLS_DHE_DSS_WITH_AES_256_CBC_SHA */ + 0x00, 0x37, /* TLS_DH_RSA_WITH_AES_256_CBC_SHA */ + 0x00, 0x36, /* TLS_DH_DSS_WITH_AES_256_CBC_SHA */ + 0x00, 0x88, /* TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA */ + 0x00, 0x87, /* TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA */ + 0x00, 0x86, /* TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA */ + 0x00, 0x85, /* TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA */ + 0xc0, 0x19, /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ + 0x00, 0x3a, /* TLS_DH_anon_WITH_AES_256_CBC_SHA */ + 0x00, 0x89, /* TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA */ + 0xc0, 0x0f, /* TLS_ECDH_RSA_WITH_AES_256_CBC_SHA */ + 0xc0, 0x05, /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA */ + 0x00, 0x35, /* TLS_RSA_WITH_AES_256_CBC_SHA */ + 0x00, 0x84, /* TLS_RSA_WITH_CAMELLIA_256_CBC_SHA */ + 0x00, 0x95, /* TLS_RSA_PSK_WITH_AES_256_CBC_SHA */ + 0xc0, 0x13, /* TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */ + 0xc0, 0x09, /* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */ + 0x00, 0x33, /* TLS_DHE_RSA_WITH_AES_128_CBC_SHA */ + 0x00, 0x32, /* TLS_DHE_DSS_WITH_AES_128_CBC_SHA */ + 0x00, 0x31, /* TLS_DH_RSA_WITH_AES_128_CBC_SHA */ + 0x00, 0x30, /* TLS_DH_DSS_WITH_AES_128_CBC_SHA */ + 0x00, 0x9a, /* TLS_DHE_RSA_WITH_SEED_CBC_SHA */ + 0x00, 0x99, /* TLS_DHE_DSS_WITH_SEED_CBC_SHA */ + 0x00, 0x98, /* TLS_DH_RSA_WITH_SEED_CBC_SHA */ + 0x00, 0x97, /* TLS_DH_DSS_WITH_SEED_CBC_SHA */ + 0x00, 0x45, /* TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA */ + 0x00, 0x44, /* TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA */ + 0x00, 0x43, /* TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA */ + 0x00, 0x42, /* TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA */ + 0xc0, 0x18, /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ + 0x00, 0x34, /* TLS_DH_anon_WITH_AES_128_CBC_SHA */ + 0x00, 0x9b, /* TLS_DH_anon_WITH_SEED_CBC_SHA */ + 0x00, 0x46, /* TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA */ + 0xc0, 0x0e, /* TLS_ECDH_RSA_WITH_AES_128_CBC_SHA */ + 0xc0, 0x04, /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA */ + 0x00, 0x2f, /* TLS_RSA_WITH_AES_128_CBC_SHA */ + 0x00, 0x96, /* TLS_RSA_WITH_SEED_CBC_SHA */ + 0x00, 0x41, /* TLS_RSA_WITH_CAMELLIA_128_CBC_SHA */ + 0x00, 0x07, /* TLS_RSA_WITH_IDEA_CBC_SHA */ + 0x00, 0x94, /* TLS_RSA_PSK_WITH_AES_128_CBC_SHA */ + 0xc0, 0x11, /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ + 0xc0, 0x07, /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA */ + 0x00, 0x66, /* TLS_DHE_DSS_WITH_RC4_128_SHA */ + 0xc0, 0x16, /* TLS_ECDH_anon_WITH_RC4_128_SHA */ + 0x00, 0x18, /* TLS_DH_anon_WITH_RC4_128_MD5 */ + 0xc0, 0x0c, /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ + 0xc0, 0x02, /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ + 0x00, 0x05, /* TLS_RSA_WITH_RC4_128_SHA */ + 0x00, 0x04, /* TLS_RSA_WITH_RC4_128_MD5 */ + 0x00, 0x92, /* TLS_RSA_PSK_WITH_RC4_128_SHA */ + 0xc0, 0x12, /* TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */ + 0xc0, 0x08, /* TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA */ + 0x00, 0x16, /* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */ + 0x00, 0x13, /* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA */ + 0x00, 0x10, /* TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA */ + 0x00, 0x0d, /* TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA */ + 0xc0, 0x17, /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ + 0x00, 0x1b, /* TLS_DH_anon_WITH_3DES_EDE_CBC_SHA */ + 0xc0, 0x0d, /* TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA */ + 0xc0, 0x03, /* TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA */ + 0x00, 0x0a, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */ + 0x00, 0x93, /* TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA */ + 0x00, 0x63, /* TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA */ + 0x00, 0x15, /* TLS_DHE_RSA_WITH_DES_CBC_SHA */ + 0x00, 0x12, /* TLS_DHE_DSS_WITH_DES_CBC_SHA */ + 0x00, 0x0f, /* TLS_DH_RSA_WITH_DES_CBC_SHA */ + 0x00, 0x0c, /* TLS_DH_DSS_WITH_DES_CBC_SHA */ + 0x00, 0x1a, /* TLS_DH_anon_WITH_DES_CBC_SHA */ + 0x00, 0x62, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA */ + 0x00, 0x09, /* TLS_RSA_WITH_DES_CBC_SHA */ + 0x00, 0x61, /* TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 */ + 0x00, 0x65, /* TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA */ + 0x00, 0x64, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA */ + 0x00, 0x60, /* TLS_RSA_EXPORT1024_WITH_RC4_56_MD5 */ + 0x00, 0x14, /* TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA */ + 0x00, 0x11, /* TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA */ + 0x00, 0x0e, /* TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA */ + 0x00, 0x0b, /* TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA */ + 0x00, 0x19, /* TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA */ + 0x00, 0x08, /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA */ + 0x00, 0x06, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */ + 0x00, 0x17, /* TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 */ + 0x00, 0x03, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */ + 0xc0, 0x10, /* TLS_ECDHE_RSA_WITH_NULL_SHA */ + 0xc0, 0x06, /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ + 0xc0, 0x15, /* TLS_ECDH_anon_WITH_NULL_SHA */ + 0xc0, 0x0b, /* TLS_ECDH_RSA_WITH_NULL_SHA */ + 0xc0, 0x01, /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ + 0x00, 0x02, /* TLS_RSA_WITH_NULL_SHA */ + 0x00, 0x01, /* TLS_RSA_WITH_NULL_MD5 */ + 0x00, 0xff, /* TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ + 0x02, /* Compression Methods Length: 2 */ + 0x01, 0x00, /* DEFLATE, none */ + }; + char response[16] = {0}; + + /* Create a socket to the target. */ + s = tcpConnect(options); + + /* If a connection could not be made, return false. */ + if (s == 0) + return false; + + /* Send the SSLv3 Client Hello packet. */ + if (send(s, sslv3_client_hello_1, sizeof(sslv3_client_hello_1), 0) <= 0) { + printf_error("send() failed: %s\n", strerror(errno)); + exit(1); + } + + timestamp = htonl(time(NULL)); /* Current time stamp. */ + timestamp_bytes[0] = timestamp & 0xff; + timestamp_bytes[1] = (timestamp >> 8) & 0xff; + timestamp_bytes[2] = (timestamp >> 16) & 0xff; + timestamp_bytes[3] = (timestamp >> 24) & 0xff; + + if (send(s, timestamp_bytes, sizeof(timestamp_bytes), 0) <= 0) { + printf_error("send() failed: %s\n", strerror(errno)); + exit(1); + } + + if (send(s, sslv3_client_hello_2, sizeof(sslv3_client_hello_2), 0) <= 0) { + printf_error("send() failed: %s\n", strerror(errno)); + exit(1); + } + + /* Read a small amount of the response. */ + if (recv(s, response, sizeof(response), 0) != sizeof(response)) + goto done; /* Returns false. */ + + /* Examine response. */ + if ((response[0] == 0x16) && /* Content Type is Handshake (22) */ + (response[1] == 0x03) && (response[2] == 0x00) && /* Version is SSL 3.0 */ + (response[5] == 0x02) && /* Handshake Type is Server Hello (2) */ + (response[9] == 0x03) && (response[10] == 0x00)) /* Version is SSL 3.0 (again) */ + ret = true; + + done: + close(s); + return ret; +} + +/* Compares the list of supported ciphersuites by OpenSSL with the complete list of ciphersuites from IANA. Marks the matches so they are not re-tested again later. */ +void findMissingCiphers() { + STACK_OF(SSL_CIPHER) *cipherList = NULL; + const SSL_CIPHER *cipher = NULL; + unsigned int tls_version = 0; + uint32_t id = 0; + const SSL_METHOD *sslMethods[] = { TLSv1_client_method(), TLSv1_1_client_method(), TLSv1_2_client_method() }; + unsigned int tls_versions[] = { V1_0, V1_1, V1_2 }; + + /* For each TLS version (not including v1.3)... */ + for (int m = 0; m < (sizeof(sslMethods) / sizeof(const SSL_METHOD *)); m++) { + tls_version = tls_versions[m]; + SSL_CTX *ctx = new_CTX(sslMethods[m]); + SSL_CTX_set_cipher_list(ctx, CIPHERSUITE_LIST_ALL); + cipherList = SSL_CTX_get_ciphers(ctx); + + /* Loop through all OpenSSL ciphers... */ + for (int i = 0; i < sk_SSL_CIPHER_num(cipherList); i++) { + cipher = sk_SSL_CIPHER_value(cipherList, i); + id = SSL_CIPHER_get_protocol_id(cipher); + + /* Using the cipher ID, find the match in the IANA list. */ + for (int j = 0; j < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); j++) { + if ((missing_ciphersuites[j].id == id) && (missing_ciphersuites[j].check_tls_versions & tls_version)) { + /* Turn off the flag for this version of TLS. */ + missing_ciphersuites[j].check_tls_versions &= ~tls_version; + } + } + } + + FREE_CTX(ctx); + } +} + +/* Creates a new byte string of size BS_DEFAULT_NEW_SIZE. Caller must eventually free it with bs_free(). The caller MUST initialize the pointer to NULL, otherwise the heap will be corrupted. */ +void bs_new(bs **b) { + bs_new_size(b, BS_DEFAULT_NEW_SIZE); +} + +/* Creates a new byte string with the specified initial size (or BS_DEFAULT_NEW_SIZE if 0). Caller must eventually free it with bs_free(). The caller MUST initialize the pointer to NULL, otherwise the heap will be corrupted. */ +void bs_new_size(bs **b, size_t new_size) { + if (b == NULL) { + fprintf(stderr, "Error: bs_new*() given NULL pointer!\n"); + exit(-1); + } + + /* If this byte string was already initialized, silently free it, then continue on. */ + if (*b != NULL) + bs_free(b); + + if (new_size == 0) + new_size = BS_DEFAULT_NEW_SIZE; + + *b = calloc(1, sizeof(bs)); + if (*b == NULL) { + fprintf(stderr, "bs_new_size(): failed to allocate new buffer.\n"); + exit(-1); + } + + (*b)->buf = calloc(new_size, sizeof(unsigned char)); + if ((*b)->buf == NULL) { + fprintf(stderr, "bs_new_size(): failed to allocate new buffer.\n"); + exit(-1); + } + + (*b)->size = new_size; + (*b)->len = 0; +} + +/* De-allocates a byte string. May be safely called multiple times. Furthermore, bs_free(NULL) does nothing. */ +void bs_free(bs **b) { + if ((b == NULL) || (*b == NULL)) + return; + + free((*b)->buf); + (*b)->buf = NULL; + + (*b)->size = 0; + (*b)->len = 0; + free(*b); + *b = NULL; +} + +/* Appends an array of bytes to this byte string. The byte string is automatically re-sized if necessary. */ +#define OVERFLOW_MESSAGE "Cannot lengthen buffer without overflowing length!\n" +void bs_append_bytes(bs *b, unsigned char *bytes, size_t bytes_len) { + size_t new_len = 0, b_len = 0, b_size = 0; + + if ((b == NULL) || (bytes == NULL) || (bytes_len == 0)) + return; + + b_len = b->len; + b_size = b->size; + new_len = b_len + bytes_len; + + /* Ensure that the new length does not cause an integer overflow. */ + if ((new_len < b_len) || (new_len < bytes_len)) { + fprintf(stderr, OVERFLOW_MESSAGE); + exit(-1); + } + + /* If the buffer needs re-sizing... */ + if (new_len > b_size) { + /* Double the size of the buffer until it is larger than what we need right now. */ + while (new_len > b_size) { + /* Ensure we don't overflow the length. */ + if ((b_len * 2) < b_len) { + fprintf(stderr, OVERFLOW_MESSAGE); + exit(-1); + } + b_size = b_size * 2; + } + + /* Extend the buffer's size. */ + b->buf = realloc(b->buf, b_size); + if (b->buf == NULL) { + fprintf(stderr, "Failed to resize buffer.\n"); + exit(-1); + } + b->size = b_size; + + /* Zero out the extended buffer region; leave the existing bytes intact. */ + memset(b->buf + b_len, 0, b_size - b_len); + } + + /* Copy the new bytes into the buffer right after the existing bytes. */ + memcpy(b->buf + b_len, bytes, bytes_len); + + /* Update the number of used bytes in the buffer. */ + b->len = new_len; +} + +/* Appends a uint32_t to the byte string. */ +void bs_append_uint32_t(bs *b, uint32_t u) { + bs_append_bytes(b, (unsigned char *)&u, sizeof(uint32_t)); +} + +/* Converts an unsigned short to network-order, then appends it to the byte string. */ +void bs_append_ushort(bs *b, unsigned short us) { + uint16_t u16 = htons(us); + bs_append_bytes(b, (unsigned char *)&u16, sizeof(uint16_t)); +} + +/* Appends one byte string (src) to another (dst). */ +void bs_append_bs(bs *dst, bs *src) { + if (src == NULL) + return; + + bs_append_bytes(dst, src->buf, src->len); +} + +/* Returns the number of bytes in this byte string. */ +size_t bs_get_len(bs *b) { + if (b == NULL) + return 0; + + return b->len; +} + +/* Returns the number of bytes allocated in the underlying byte string. */ +size_t bs_get_size(bs *b) { + if (b == NULL) + return 0; + + return b->size; +} + +/* Gets the bytes of this byte string. The caller must _never_ free it directly themselves. */ +unsigned char *bs_get_bytes(bs *b) { + if (b == NULL) + return NULL; + + return b->buf; +} + +/* Gets a single byte from the offset position. Performs safety checks that the read will not overflow. Returns 0 if out of bounds. */ +unsigned char bs_get_byte(bs *b, size_t offset) { + if ((b == NULL) || (offset >= b->len)) + return 0; + + return b->buf[offset]; +} + +/* Gets a single byte from the offset position. Performs safety checks that the read will not overflow. */ +void bs_set_byte(bs *b, size_t offset, unsigned char byte) { + if ((b == NULL) || (offset >= b->len)) + return; + + b->buf[offset] = byte; +} + +/* Sets a length field in a TLS packet at the specified offset. */ +void bs_set_ushort(bs *b, size_t offset, unsigned short length) { + uint16_t u = htons(length); + + bs_set_byte(b, offset, (unsigned char)u); + bs_set_byte(b, offset + 1, (unsigned char)(u >> 8)); +} + +/* Reads the specified number of bytes from socket s into byte string b. Returns 0 on success, or errno on error. */ +int bs_read_socket(bs *b, int s, size_t num_bytes) { + int ret = -1, n = 0; + unsigned int i = 0; + size_t old_len = 0, bytes_read = 0; + + if (b == NULL) + return -1; + + /* Append num_bytes to the byte string to ensure that the underlying buffer is resized appropriately. Then reset the length. */ + old_len = b->len; + for (; i < (num_bytes / sizeof(uint32_t)) + 1; i++) + bs_append_uint32_t(b, 0); + + b->len = old_len; + + /* Read in num_bytes from the socket and store it in the underlying buffer. */ + bytes_read = 0; + while (bytes_read < num_bytes) { + n = recv(s, b->buf + b->len + bytes_read, num_bytes - bytes_read, 0); + if (n <= 0) { + if ((errno != 0) && (errno != ECONNRESET)) + ret = errno; + + b->len += bytes_read; + goto err; + } + bytes_read += n; + } + b->len += bytes_read; + ret = 0; + +err: + return ret; +} + + +/* Returns true if a specific TLS version is supported by the server. */ +unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsigned int tls_version) { + bs *tls_extensions = NULL, *ciphersuite_list = NULL, *client_hello = NULL, *server_hello = NULL; + int ret = false, s = -1; + + + tls_extensions = makeTLSExtensions(options, 1); + if (tls_version == TLSv1_2) { + /* Extension: supported_groups */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x0a, // Extension: supported_groups (10) + 0x00, 0x1c, // Extension Length (28) + 0x00, 0x1a, // Supported Groups List Length (26) + 0x00, 0x17, // secp256r1 + 0x00, 0x19, // secp521r1 + 0x00, 0x1c, // brainpoolP512r1 + 0x00, 0x1b, // brainpoolP384r1 + 0x00, 0x18, // secp384r1 + 0x00, 0x1a, // brainpoolP256r1 + 0x00, 0x16, // secp256k1 + 0x00, 0x0e, // sect571r1 + 0x00, 0x0d, // sect571k1 + 0x00, 0x0b, // sect409k1 + 0x00, 0x0c, // sect409r1 + 0x00, 0x09, // sect283k1 + 0x00, 0x0a, // sect283r1 + }, 32); + + /* Update the length of the extensions. */ + tlsExtensionUpdateLength(tls_extensions); + } else if (tls_version == TLSv1_3) { + /* Extension: supported_groups */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x0a, // Extension: supported_groups (10) + 0x00, 0x16, // Extension Length (22) + 0x00, 0x14, // Supported Groups List Length (20) + 0x00, 0x17, // secp256r1 + 0x00, 0x19, // secp521r1 + 0x00, 0x18, // secp384r1 + 0x00, 0x1d, // X25519 + 0x00, 0x1e, // X448 + 0x01, 0x00, // FFDHE2048 + 0x01, 0x01, // FFDHE3072 + 0x01, 0x02, // FFDHE4096 + 0x01, 0x03, // FFDHE6144 + 0x01, 0x04, // FFDHE8192 + }, 26); + + /* Add key share for X25519. */ + tlsExtensionAddDefaultKeyShare(tls_extensions); + + /* Explicitly mark that this is a TLSv1.3 Client Hello. */ + tlsExtensionAddTLSv1_3(tls_extensions); + + /* Update the length of the extensions. */ + tlsExtensionUpdateLength(tls_extensions); + } + + ciphersuite_list = makeCiphersuiteListAll(tls_version); + client_hello = makeClientHello(options, tls_version, ciphersuite_list, tls_extensions); + bs_free(&ciphersuite_list); + bs_free(&tls_extensions); + + /* Now connect to the target server. */ + s = tcpConnect(options); + if (s == 0) + goto done; + + /* Send the Client Hello message. */ + if (send(s, bs_get_bytes(client_hello), bs_get_len(client_hello), 0) <= 0) { + printf_error("send() failed while sending Client Hello: %d (%s)\n", errno, strerror(errno)); + goto done; /* Returns false. */ + } + bs_free(&client_hello); + + server_hello = getServerHello(s); + + /* If we don't receive a proper Server Hello message, then this TLS version is not supported. */ + if (server_hello == NULL) + goto done; + + unsigned int expected_tls_version_low = tls_version + 1; + if (tls_version == TLSv1_3) + expected_tls_version_low = 3; + + /* Get the server's TLS version and compare it with what we sent. */ + unsigned int server_tls_version_high = bs_get_byte(server_hello, 9); + unsigned int server_tls_version_low = bs_get_byte(server_hello, 10); + if ((server_tls_version_high != 3) || (server_tls_version_low != expected_tls_version_low)) + goto done; + + /* A valid Server Hello was returned, so this TLS version is supported. */ + ret = true; + + done: + CLOSE(s); + bs_free(&ciphersuite_list); + bs_free(&tls_extensions); + bs_free(&client_hello); + bs_free(&server_hello); + return ret; +} + +/* Given a TLSv1_? constant, return its printable string representation. */ +char *getPrintableTLSName(unsigned int tls_version) { + switch (tls_version) { + case TLSv1_0: + return "TLSv1.0"; + case TLSv1_1: + return "TLSv1.1"; + case TLSv1_2: + return "TLSv1.2"; + case TLSv1_3: + return "TLSv1.3"; + default: + return "Unknown"; + } +} + +/* Returns a byte string of all TLSv1.3 cipher suites. The caller must eventually call bs_free() on it. */ +bs *makeCiphersuiteListTLS13All() { + bs *ciphersuite_list = NULL; + + bs_new_size(&ciphersuite_list, 16); + bs_append_bytes(ciphersuite_list, (unsigned char []) { + 0x13, 0x01, // TLS_AES_128_GCM_SHA256 + 0x13, 0x02, // TLS_AES_256_GCM_SHA384 + 0x13, 0x03, // TLS_CHACHA20_POLY1305_SHA256 + 0x13, 0x04, // TLS_AES_128_CCM_SHA256 + 0x13, 0x05, // TLS_AES_128_CCM_8_SHA256 + }, 10); + + return ciphersuite_list; +} + + +/* Returns a byte string with a list of all ciphersuites registered by IANA. */ +bs *makeCiphersuiteListAll(unsigned int tls_version) { + bs *ciphersuite_list = NULL; + + /* If its TLSv1.3, return the smaller v1.3-specific list. */ + if (tls_version == TLSv1_3) + return makeCiphersuiteListTLS13All(); + + bs_new_size(&ciphersuite_list, 1024); + + for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { + if (!strstr(missing_ciphersuites[i].protocol_name, "PRIVATE_CIPHER_")) + bs_append_ushort(ciphersuite_list, missing_ciphersuites[i].id); + } + + return ciphersuite_list; +} + + +/* Returns a byte string with a list of all missing ciphersuites for a given TLS version (TLSv1_? constant) .*/ +bs *makeCiphersuiteListMissing(unsigned int tls_version) { + bs *ciphersuite_list = NULL; + + bs_new_size(&ciphersuite_list, 1024); + + if (tls_version == TLSv1_0) + tls_version = V1_0; + else if (tls_version == TLSv1_1) + tls_version = V1_1; + else if (tls_version == TLSv1_2) + tls_version = V1_2; + + for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { + /* Append only those that OpenSSL does not cover, and those that were not already accepted through a previous run. */ + if ((missing_ciphersuites[i].check_tls_versions & tls_version) && ((missing_ciphersuites[i].accepted_tls_versions & tls_version) == 0)) { + bs_append_ushort(ciphersuite_list, missing_ciphersuites[i].id); + } + } + + return ciphersuite_list; +} + +/* Marks a ciphersuite as found so that it is not re-tested again. */ +void markFoundCiphersuite(unsigned short server_cipher_id, unsigned int tls_version) { + if (tls_version == TLSv1_0) + tls_version = V1_0; + else if (tls_version == TLSv1_1) + tls_version = V1_1; + else if (tls_version == TLSv1_2) + tls_version = V1_2; + + for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { + if (missing_ciphersuites[i].id == server_cipher_id) { + missing_ciphersuites[i].accepted_tls_versions |= tls_version; + break; + } + } +} + +/* Resolves an IANA cipher ID to its IANA name. Sets the cipher_bits argument to the cipher strength (or to -1 if unknown). Returns "UNKNOWN_CIPHER if cipher ID is not found. */ +char *resolveCipherID(unsigned short cipher_id, int *cipher_bits) { + for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { + if (missing_ciphersuites[i].id == cipher_id) { + *cipher_bits = missing_ciphersuites[i].bits; + return missing_ciphersuites[i].protocol_name; + } + } + *cipher_bits = -1; + return "UNKNOWN_CIPHER"; +} + +/* Creates a basic set of TLS extensions, including SNI, ec_point_formats, Session Ticket TLS, and signature_algorithms. */ +bs *makeTLSExtensions(struct sslCheckOptions *options, unsigned int include_signature_algorithms) { + bs *tls_extensions = NULL; + + bs_new_size(&tls_extensions, 64); + + /* Add the length of the extensions (to be filled in later). */ + bs_append_ushort(tls_extensions, 0); + + /* Extension: server name */ + uint16_t sni_length = strlen(options->sniname); + uint16_t sni_list_length = sni_length + 3; + uint16_t extension_length = sni_list_length + 2; + + bs_append_ushort(tls_extensions, 0x0000); /* Extension: server_name */ + bs_append_ushort(tls_extensions, extension_length); + bs_append_ushort(tls_extensions, sni_list_length); + bs_append_bytes(tls_extensions, (unsigned char []) { 0x00 /* Server Name Type: host_name */ }, 1); + bs_append_ushort(tls_extensions, sni_length); /* The length of the hostname. */ + bs_append_bytes(tls_extensions, (unsigned char *)options->sniname, sni_length); /* The hostname itself. */ + + /* Extension: ec_point_formats */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x0b, // Extension: ec_point_formats (11) + 0x00, 0x04, // Extension Length (4) + 0x03, // EC Point Formats Length (3) + 0x00, // Uncompressed + 0x01, // ansiX962_compressed_prime + 0x02, // ansiX962_compressed_char2 + }, 8); + + /* Extension: SessionTicket TLS */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x23, // Extension: SessionTicket TLS (35) + 0x00, 0x00, // Extension Length (0) + }, 4); + + if (include_signature_algorithms) { + /* Extension: signature_algorithms */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x0d, // Extension: signature_algorithms (13) + 0x00, 0x30, // Extension Length (48) + 0x00, 0x2e, // Signature Hash Algorithms Length (46) + 0x08, 0x04, // rsa_pss_rsae_sha256 + 0x08, 0x05, // rsa_pss_rsae_sha384 + 0x08, 0x06, // rsa_pss_rsae_sha512 + 0x08, 0x07, // ed25519 + 0x08, 0x08, // ed448 + 0x08, 0x09, // rsa_pss_pss_sha256 + 0x08, 0x0a, // rsa_pss_pss_sha384 + 0x08, 0x0b, // rsa_pss_pss_sha512 + 0x06, 0x01, // rsa_pkcs1_sha512 + 0x06, 0x02, // SHA512 DSA + 0x06, 0x03, // ecdsa_secp521r1_sha512 + 0x05, 0x01, // rsa_pkcs1_sha384 + 0x05, 0x02, // SHA384 DSA + 0x05, 0x03, // ecdsa_secp384r1_sha384 + 0x04, 0x01, // rsa_pkcs1_sha256" + 0x04, 0x02, // SHA256 DSA + 0x04, 0x03, // ecdsa_secp256r1_sha256 + 0x03, 0x01, // SHA224 ECDSA + 0x03, 0x02, // SHA224 DSA + 0x03, 0x03, // SHA224 ECDSA + 0x02, 0x01, // rsa_pkcs1_sha1 + 0x02, 0x02, // SHA1 DSA + 0x02, 0x03, // ecdsa_sha1 + }, 52); + } + + /* Set the extension length. */ + tlsExtensionUpdateLength(tls_extensions); + return tls_extensions; +} + +/* Adds the TLS supported_versions extension, set to TLSv1.3 only. */ +void tlsExtensionAddTLSv1_3(bs *tls_extensions) { + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x2b, // supported_versions (43) + 0x00, 0x03, // Length + 0x02, // Supported Versions Length + 0x03, 0x04, // Supported Version: TLS v1.3 + }, 7); + tlsExtensionUpdateLength(tls_extensions); +} + +/* Adds default key_share extension. */ +void tlsExtensionAddDefaultKeyShare(bs *tls_extensions) { + + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x33, // key_share (51) + 0x00, 0x26, // Length (38) + 0x00, 0x24, // Key Share List Length (36) + 0x00, 0x1d, // Group ID (X25519) + 0x00, 0x20, // Key Exchange Length (32) + }, 10); + + /* Add 32 bytes of the (bogus) X25519 key share. */ + srand(time(NULL) ^ 0xbeefdead); + for (int i = 0; i < 32; i++) { + unsigned char c = (unsigned char)rand(); + bs_append_bytes(tls_extensions, &c, 1); + } + + /* Update the length of the extensions. */ + tlsExtensionUpdateLength(tls_extensions); +} + +/* Retrieves a TLS Handshake record, or returns NULL on error. */ +bs *getTLSHandshakeRecord(int s) { + bs *tls_record = NULL; + bs_new_size(&tls_record, 512); + + /* Read in the first 5 bytes to get the length of the rest of the record. */ + int err = bs_read_socket(tls_record, s, 5); + if (err != 0) + goto err; + + /* Ensure that the Content Type is Handshake (22). */ + if (bs_get_byte(tls_record, 0) != 0x16) + goto err; + + /* Get the length of the record. */ + unsigned short packet_len = (bs_get_byte(tls_record, 3) << 8) | bs_get_byte(tls_record, 4); + + /* Read in the rest of the record. */ + err = bs_read_socket(tls_record, s, packet_len); + if (err != 0) + goto err; + + return tls_record; + + err: + bs_free(&tls_record); + return NULL; +} + +/* Update the length of the TLS extensions. */ +void tlsExtensionUpdateLength(bs *tls_extensions) { + bs_set_ushort(tls_extensions, 0, bs_get_len(tls_extensions) - 2); +} + +/* From socket s, reads a ServerHello from the network. Returns a byte string on success (which the caller must bs_free()), or NULL on failure. */ +bs *getServerHello(int s) { + bs *server_hello = getTLSHandshakeRecord(s); + + if (server_hello == NULL) + goto err; + + /* Ensure that the Handshake Type is Server Hello (2). */ + if (bs_get_byte(server_hello, 5) != 0x02) + goto err; + + return server_hello; + + err: + bs_free(&server_hello); + return NULL; +} + +/* Returns a byte string (which the caller must later bs_free()) containing a TLS Client Hello message. The 'tls_version' must be one of the TLSv1_? constants. The specified ciphersuite list and TLS extensions will be included. */ +bs *makeClientHello(struct sslCheckOptions *options, unsigned int tls_version, bs *ciphersuite_list, bs *tls_extensions) { + bs *client_hello = NULL; + unsigned int tls_record_version_low_byte = 1, tls_handshake_version_low_byte = 1; + time_t time_now = time(NULL); + + + /* For TLSv1.0, 1.1, and 1.2, the TLS Record version and Handshake version are the same (and what they should be). For TLSv1.3, the TLS Record claims to be TLSv1.0 and the Handshake claims to be TLSv1.2; this is for compatibility of buggy middleware that most implementations follow. */ + if (tls_version < TLSv1_3) { + tls_record_version_low_byte += tls_version; + tls_handshake_version_low_byte += tls_version; + } else { + tls_record_version_low_byte = 1; + tls_handshake_version_low_byte = 3; + } + + /* Allocate byte string for the Client Hello and TLS extensions. */ + bs_new_size(&client_hello, 1024); + + /* Build the TLSv1 Record with the ClientHello message. */ + bs_append_bytes(client_hello, (unsigned char []) { + 0x16, // Content Type: Handshake (22) + 0x03, (unsigned char)tls_record_version_low_byte, // Version: TLS 1.x + 0x00, 0x00, // Length (to be filled in later) + 0x01, // Handshake Type: Client Hello + 0x00, 0x00, 0x00, // Length (to be filled in later) + 0x03, (unsigned char)tls_handshake_version_low_byte, // Version: TLS 1.x + }, 11); + + /* "Random" 32 bytes. */ + uint32_t rand = htonl(time_now); + bs_append_uint32_t(client_hello, rand); /* The first 4 bytes is the timestamp. */ + + for (int i = 1; i < 8; i++) { + rand = rand + (time_now ^ (uint32_t)((~(i + 0) << 24) | (~(i + 1) << 16) | (~(i + 2) << 8) | (~(i + 3) << 0))); + bs_append_uint32_t(client_hello, rand); + } + + /* Session ID Length: 0 */ + bs_append_bytes(client_hello, (unsigned char []) { 0x00 }, 1); + + /* Add the length (in bytes) of the ciphersuites list to the Client Hello. */ + bs_append_ushort(client_hello, bs_get_len(ciphersuite_list)); + + /* Add the ciphersuite list. */ + bs_append_bs(client_hello, ciphersuite_list); + + /* Add the compression options. */ + bs_append_bytes(client_hello, (unsigned char []) { + 0x01, // Compression Methods Length (1) + 0x00 // Compression Method: null (0) + }, 2); + + /* Add the extensions to the Client Hello. */ + bs_append_bs(client_hello, tls_extensions); + + /* Set the length of the Client Hello. */ + bs_set_byte(client_hello, 6, 0); + bs_set_ushort(client_hello, 7, bs_get_len(client_hello) - 9); + + /* Set the length of the Record Layer. */ + bs_set_ushort(client_hello, 3, bs_get_len(client_hello) - 5); + return client_hello; +} + +/* Checks all ciphersuites that OpenSSL does not support. When version is 0, TLSv1.0 is tested. When set to 1, TLSv1.1 is tested. When set to 2, TLSv1.2 is tested. */ +int testMissingCiphers(struct sslCheckOptions *options, unsigned int tls_version) { + int ret = false, s = -1; + unsigned int tls_version_low_byte = 1; + char *tls_printable_name = getPrintableTLSName(tls_version); + bs *client_hello = NULL, *server_hello = NULL, *ciphersuite_list = NULL, *tls_extensions = NULL; + + + tls_version_low_byte += tls_version; + + /* Continue until a Server Hello isn't received. */ + while (1) { + int cipher_bits = -1; + char *cipher_name = NULL; + struct timeval tval_start = {0}, tval_end = {0}, tval_elapsed = {0}; + + + gettimeofday(&tval_start, NULL); + + tls_extensions = makeTLSExtensions(options, 1); + + /* Extension: supported_groups */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x0a, // Extension: supported_groups (10) + 0x00, 0x1c, // Extension Length (28) + 0x00, 0x1a, // Supported Groups List Length (26) + 0x00, 0x17, // secp256r1 + 0x00, 0x19, // secp521r1 + 0x00, 0x1c, // brainpoolP512r1 + 0x00, 0x1b, // brainpoolP384r1 + 0x00, 0x18, // secp384r1 + 0x00, 0x1a, // brainpoolP256r1 + 0x00, 0x16, // secp256k1 + 0x00, 0x0e, // sect571r1 + 0x00, 0x0d, // sect571k1 + 0x00, 0x0b, // sect409k1 + 0x00, 0x0c, // sect409r1 + 0x00, 0x09, // sect283k1 + 0x00, 0x0a, // sect283r1 + }, 32); + + tlsExtensionUpdateLength(tls_extensions); + + /* Construct the list of all ciphersuites not implemented by OpenSSL. */ + ciphersuite_list = makeCiphersuiteListMissing(tls_version); + + client_hello = makeClientHello(options, tls_version, ciphersuite_list, tls_extensions); + bs_free(&ciphersuite_list); + bs_free(&tls_extensions); + + /* Now connect to the target server. */ + s = tcpConnect(options); + if (s == 0) + goto done; + + /* Send the Client Hello message. */ + if (send(s, bs_get_bytes(client_hello), bs_get_len(client_hello), 0) <= 0) { + printf_error("send() failed while sending Client Hello: %d (%s)\n", errno, strerror(errno)); + goto done; /* Returns false. */ + } + bs_free(&client_hello); + + server_hello = getServerHello(s); + + /* If we don't receive a proper Server Hello message, or its too short, abort. We need to reach at least the session ID field (offset 44). */ + if ((server_hello == NULL) || (bs_get_len(server_hello) < 44)) + goto done; + + /* Close the socket, since we're done reading. */ + CLOSE(s); + + /* Check that the TLS version returned is what we sent earlier. */ + if ((bs_get_byte(server_hello, 1) != 0x03) || (bs_get_byte(server_hello, 2) != (unsigned char)tls_version_low_byte)) + goto done; + + /* At this point, the test is considered a success, even if the server rejects our Client Hello. */ + ret = true; + + /* Get the length of the session ID. We must jump over this to reach the ciphersuite selected by the server. */ + unsigned int session_id_len = bs_get_byte(server_hello, 43); + + /* Its impossible for one byte to overflow an unsigned int (on any modern hardware), but still... */ + if ((session_id_len + 43 + 2 + 1) < session_id_len) { + fprintf(stderr, "Error: potential integer overflow averted (%d).\n", session_id_len); + exit(-1); + } + + /* Check that the session ID length wouldn't put us past our buffer boundary. */ + if ((session_id_len + 43 + 2 + 1) > bs_get_len(server_hello)) { + fprintf(stderr, "Error: size of server_hello (%"SIZE_T_FMT") is not large enough to reach cipher suite (%u).\n", sizeof(server_hello), session_id_len + 43 + 2); + exit(-1); + } + + /* Extract the cipher ID. */ + unsigned short cipher_id = (bs_get_byte(server_hello, session_id_len + 43 + 1) << 8) | bs_get_byte(server_hello, session_id_len + 43 + 2); + + bs_free(&server_hello); + + /* Mark this cipher ID as supported by the server, so when we loop again, the next ciphersuite list doesn't include it. */ + markFoundCiphersuite(cipher_id, tls_version); + + /* Get the IANA name and cipher bit strength (maybe -1 when unknown). */ + cipher_name = resolveCipherID(cipher_id, &cipher_bits); + + /* Get the number of milliseconds that have elapsed. */ + gettimeofday(&tval_end, NULL); + timersub(&tval_end, &tval_start, &tval_elapsed); + unsigned int milliseconds_elapsed = tval_elapsed.tv_sec * 1000 + (int)tval_elapsed.tv_usec / 1000; + + /* Output the cipher information. */ + outputCipher(options, NULL, tls_printable_name, cipher_id, cipher_name, cipher_bits, 1, milliseconds_elapsed, ""); + } + + done: + CLOSE(s); + bs_free(&ciphersuite_list); + bs_free(&tls_extensions); + bs_free(&client_hello); + bs_free(&server_hello); + return ret; +} + +/* Enumerates all the group key exchanges supported by the server. Tests the highest supported protocol between TLSv1.0 and v1.2, along with TLSv1.3 (if enabled). */ +int testSupportedGroups(struct sslCheckOptions *options) { + int ret = true, s = -1; + unsigned int printed_header = 0; + int test_versions[2] = {-1, -1}; + bs *client_hello = NULL, *ciphersuite_list = NULL, *tls_extensions = NULL, *server_hello = NULL, *key_exchange = NULL; + + struct group_key_exchange { + uint16_t group_id; + char *group_name; + unsigned int group_bit_strength; /* The bit strength equivalent of this group. */ + char *color; + int nid; /* NID for group, or -1 for X25519/X448. */ + unsigned int nid_type; /* One of the NID_TYPE_* flags. */ + uint16_t key_exchange_len; + }; + + + /* Auto-generated by ./tools/iana_tls_supported_groups_parser.py on December 24, 2019. */ +#define COL_PLAIN "" +#define NID_TYPE_NA 0 /* Not Applicable (i.e.: X25519/X448) */ +#define NID_TYPE_ECDHE 1 /* For ECDHE curves (sec*, P-256/384-521) */ +#define NID_TYPE_DHE 2 /* For ffdhe* */ + /* Bit strength of DHE 2048 and 3072-bit moduli is taken directly from NIST SP 800-57 pt.1, rev4., pg. 53; DHE 4096, 6144, and 8192 are estimated using that document. */ + struct group_key_exchange group_key_exchanges[] = { + {0x0001, "sect163k1", 81, COL_RED, NID_sect163k1, NID_TYPE_ECDHE, 0}, + {0x0002, "sect163r1", 81, COL_RED, NID_sect163r1, NID_TYPE_ECDHE, 0}, + {0x0003, "sect163r2", 81, COL_RED, NID_sect163r2, NID_TYPE_ECDHE, 0}, + {0x0004, "sect193r1", 96, COL_RED, NID_sect193r1, NID_TYPE_ECDHE, 0}, + {0x0005, "sect193r2", 96, COL_RED, NID_sect193r2, NID_TYPE_ECDHE, 0}, + {0x0006, "sect233k1", 116, COL_PLAIN, NID_sect233k1, NID_TYPE_ECDHE, 0}, + {0x0007, "sect233r1", 116, COL_PLAIN, NID_sect233r1, NID_TYPE_ECDHE, 0}, + {0x0008, "sect239k1", 119, COL_PLAIN, NID_sect239k1, NID_TYPE_ECDHE, 0}, + {0x0009, "sect283k1", 141, COL_PLAIN, NID_sect283k1, NID_TYPE_ECDHE, 0}, + {0x000a, "sect283r1", 141, COL_PLAIN, NID_sect283r1, NID_TYPE_ECDHE, 0}, + {0x000b, "sect409k1", 204, COL_PLAIN, NID_sect409k1, NID_TYPE_ECDHE, 0}, + {0x000c, "sect409r1", 204, COL_PLAIN, NID_sect409r1, NID_TYPE_ECDHE, 0}, + {0x000d, "sect571k1", 285, COL_PLAIN, NID_sect571k1, NID_TYPE_ECDHE, 0}, + {0x000e, "sect571r1", 285, COL_PLAIN, NID_sect571r1, NID_TYPE_ECDHE, 0}, + {0x000f, "secp160k1", 80, COL_RED, NID_secp160k1, NID_TYPE_ECDHE, 0}, + {0x0010, "secp160r1", 80, COL_RED, NID_secp160r1, NID_TYPE_ECDHE, 0}, + {0x0011, "secp160r2", 80, COL_RED, NID_secp160r2, NID_TYPE_ECDHE, 0}, + {0x0012, "secp192k1", 96, COL_RED, NID_secp192k1, NID_TYPE_ECDHE, 0}, + {0x0013, "secp192r1", 96, COL_RED, NID_X9_62_prime192v1, NID_TYPE_ECDHE, 0}, + {0x0014, "secp224k1", 112, COL_PLAIN, NID_secp224k1, NID_TYPE_ECDHE, 0}, + {0x0015, "secp224r1", 112, COL_PLAIN, NID_secp224r1, NID_TYPE_ECDHE, 0}, + {0x0016, "secp256k1", 128, COL_GREEN, NID_secp256k1, NID_TYPE_ECDHE, 0}, + {0x0017, "secp256r1 (NIST P-256)", 128, COL_PLAIN, NID_X9_62_prime256v1, NID_TYPE_ECDHE, 0}, + {0x0018, "secp384r1 (NIST P-384)", 192, COL_PLAIN, NID_secp384r1, NID_TYPE_ECDHE, 0}, + {0x0019, "secp521r1 (NIST P-521)", 260, COL_PLAIN, NID_secp521r1, NID_TYPE_ECDHE, 0}, + {0x001a, "brainpoolP256r1", 128, COL_PLAIN, NID_brainpoolP256r1, NID_TYPE_ECDHE, 0}, + {0x001b, "brainpoolP384r1", 192, COL_PLAIN, NID_brainpoolP384r1, NID_TYPE_ECDHE, 0}, + {0x001c, "brainpoolP512r1", 256, COL_PLAIN, NID_brainpoolP512r1, NID_TYPE_ECDHE, 0}, + {0x001d, "x25519", 128, COL_GREEN, -1, NID_TYPE_NA, 32}, + {0x001e, "x448", 224, COL_GREEN, -1, NID_TYPE_NA, 56}, + {0x0100, "ffdhe2048", 112, COL_PLAIN, NID_ffdhe2048, NID_TYPE_DHE, 256}, + {0x0101, "ffdhe3072", 128, COL_PLAIN, NID_ffdhe3072, NID_TYPE_DHE, 384}, + {0x0102, "ffdhe4096", 150, COL_PLAIN, NID_ffdhe4096, NID_TYPE_DHE, 512}, + {0x0103, "ffdhe6144", 175, COL_PLAIN, NID_ffdhe6144, NID_TYPE_DHE, 768}, + {0x0104, "ffdhe8192", 192, COL_PLAIN, NID_ffdhe8192, NID_TYPE_DHE, 1024}, + }; + + + /* If TLSv1.3 is supported, test it first. */ + unsigned int index = 0; + if (options->tls13_supported) { + test_versions[index] = TLSv1_3; + index++; + } + + /* For TLSv1.2 and below, test the highest protocol version supported. */ + if (options->tls12_supported) + test_versions[index] = TLSv1_2; + else if (options->tls11_supported) + test_versions[index] = TLSv1_1; + else if (options->tls10_supported) + test_versions[index] = TLSv1_0; + + /* Loop through the one or two TLS versions to test. */ + for (index = 0; index < (sizeof(test_versions) / sizeof(int)); index++) { + int tls_version = test_versions[index]; + + /* If there's only one version to test... */ + if (tls_version == -1) + break; + + if (tls_version == TLSv1_3) + ciphersuite_list = makeCiphersuiteListAll(tls_version); + else { + /* For some reason, with TLSv1.2 (and maybe below), passing all ciphersuites causes false negatives. So we use a string of bytes sniffed from an OpenSSL client connection. */ + bs_new(&ciphersuite_list); + bs_append_bytes(ciphersuite_list, (unsigned char []) { 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0xa5, 0x00, 0xa3, 0x00, 0xa1, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x69, 0x00, 0x68, 0x00, 0x39, 0x00, 0x38, 0x00, 0x37, 0x00, 0x36, 0x00, 0x88, 0x00, 0x87, 0x00, 0x86, 0x00, 0x85, 0xc0, 0x32, 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f, 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0xa4, 0x00, 0xa2, 0x00, 0xa0, 0x00, 0x9e, 0x00, 0x67, 0x00, 0x40, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x33, 0x00, 0x32, 0x00, 0x31, 0x00, 0x30, 0x00, 0x9a, 0x00, 0x99, 0x00, 0x98, 0x00, 0x97, 0x00, 0x45, 0x00, 0x44, 0x00, 0x43, 0x00, 0x42, 0xc0, 0x31, 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e, 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x96, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13, 0x00, 0x10, 0x00, 0x0d, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0x00, 0xff }, 170); + } + + /* For each key exchange group... */ + for (int i = 0; i < (sizeof(group_key_exchanges) / sizeof(struct group_key_exchange)); i++) { + uint16_t group_id = group_key_exchanges[i].group_id; + char *group_name = group_key_exchanges[i].group_name; + char *color = group_key_exchanges[i].color; + unsigned int group_bit_strength = group_key_exchanges[i].group_bit_strength; + int nid = group_key_exchanges[i].nid; + unsigned nid_type = group_key_exchanges[i].nid_type; + uint16_t key_exchange_len = group_key_exchanges[i].key_exchange_len; + + /* This will hold the key exchange data that we send to the server. */ + bs_new_size(&key_exchange, key_exchange_len); + + /* Generate the right type of key exchange data. */ + if (nid_type == NID_TYPE_NA) { + + /* Generate "random" data. X25519 and X448 public keys have no discernible structure. */ + srand(time(NULL) ^ 0xdeadbeef); + for (int j = 0; j < key_exchange_len; j++) { + unsigned char c = (unsigned char)rand(); + bs_append_bytes(key_exchange, &c, 1); + } + + } else if (nid_type == NID_TYPE_ECDHE) { + + /* Generate the ECDHE key. */ + EC_KEY *key = EC_KEY_new_by_curve_name(nid); + if ((key == NULL) || (EC_KEY_generate_key(key) != 1)) { + EC_KEY_free(key); key = NULL; + fprintf(stderr, "Failed to generate ECDHE key for nid %d\n", nid); + continue; + } + + /* Allocate a *new* byte array and put the key into it. */ + unsigned char *kex_buf = NULL; + key_exchange_len = EC_KEY_key2buf(key, POINT_CONVERSION_UNCOMPRESSED, &kex_buf, NULL); + if (kex_buf == NULL) { + EC_KEY_free(key); key = NULL; + fprintf(stderr, "Failed to obtain ECDHE public key bytes.\n"); + continue; + } + + bs_append_bytes(key_exchange, kex_buf, key_exchange_len); + OPENSSL_free(kex_buf); kex_buf = NULL; + EC_KEY_free(key); key = NULL; + + } else if (nid_type == NID_TYPE_DHE) { + + /* The value (Y) for FFDHE group must be 1 < Y < p - 1 (see RFC7919). Furthermore, GnuTLS checks that Y ^ q mod p == 1 (see GnuTLS v3.6.11.1, lib/nettle/pk.c:291). The easiest way to do this seems to be to actually generate real DH public keys. */ + DH *dh = DH_new_by_nid(nid); + if (!DH_generate_key(dh)) { + bs_free(&key_exchange); + fprintf(stderr, "Failed to generate DH key for nid %d\n", nid); + continue; + } + + /* Make array to read in DH public key. */ + unsigned int bytes_len = key_exchange_len; + unsigned char *bytes = calloc(bytes_len, sizeof(unsigned char)); + if (bytes == NULL) { + fprintf(stderr, "Failed to allocate buffer for key.\n"); + exit(-1); + } + + /* Export the public key to our array. */ + const BIGNUM *pub_key = NULL; + DH_get0_key(dh, &pub_key, NULL); + if (!BN_bn2binpad(pub_key, bytes, bytes_len)) { + bs_free(&key_exchange); + fprintf(stderr, "Failed to get DH key for nid %d\n", nid); + continue; + } + + /* Add the bytes to our byte string. */ + bs_append_bytes(key_exchange, bytes, bytes_len); + FREE(bytes); bytes_len = 0; + + } else { + /* Use the provided value, since it must be a specific format. */ + fprintf(stderr, "Error: unknown NID_TYPE in struct: %d\n", nid_type); + exit(-1); + } + + /* Make generic TLS extensions (with SNI, accepted EC point formats, etc). */ + tls_extensions = makeTLSExtensions(options, 1); + + /* Add the supported_versions extension to signify we are using TLS v1.3. */ + if (tls_version == TLSv1_3) + tlsExtensionAddTLSv1_3(tls_extensions); + + /* Add the supported_groups extension. Only add the one group we are testing for. */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x0a, // Extension Type: supported_groups (10) + 0x00, 0x04, // Extension Length (4) + 0x00, 0x02, // Supported Groups List Length (2) + }, 6); + bs_append_ushort(tls_extensions, group_id); + + /* Only add the key_share extension if we're using TLS v1.3. */ + if (tls_version == TLSv1_3) { + /* Add the key_share extension for the current group type. */ + bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x33 }, 2); // Extension Type: key_share (51) + bs_append_ushort(tls_extensions, bs_get_len(key_exchange) + 6); // Extension Length + bs_append_ushort(tls_extensions, bs_get_len(key_exchange) + 4); // Client Key Share Length + bs_append_ushort(tls_extensions, group_id); // Group ID. + bs_append_ushort(tls_extensions, bs_get_len(key_exchange)); // Key Exchange Length + bs_append_bs(tls_extensions, key_exchange); // Key Exchange + } + bs_free(&key_exchange); + + /* Update the TLS extensions length since we manually added to it. */ + tlsExtensionUpdateLength(tls_extensions); + + /* Create the Client Hello buffer using the ciphersuite list and TLS extensions. */ + client_hello = makeClientHello(options, tls_version, ciphersuite_list, tls_extensions); + + /* Free the TLS extensions since we're done with them. Note: we don't free the ciphersuite_list because we'll need them on the next loop. */ + bs_free(&tls_extensions); + + CLOSE(s); /* In case the last loop left the socket open. */ + + /* Now connect to the target server. */ + s = tcpConnect(options); + if (s == 0) { + ret = false; + goto done; + } + + /* Send the Client Hello message. */ + if (send(s, bs_get_bytes(client_hello), bs_get_len(client_hello), 0) <= 0) { + printf_error("send() failed while sending Client Hello: %d (%s)\n", errno, strerror(errno)); + ret = false; + goto done; + } + bs_free(&client_hello); + + server_hello = getServerHello(s); + + /* This group is definitely not supported. */ + if (server_hello == NULL) { + CLOSE(s); + continue; + } + + bs_free(&server_hello); + + /* For TLSv1.2 and below, we need to examine the Server Key Exchange record. */ + if (tls_version < TLSv1_3) { + bs *tls_record = getTLSHandshakeRecord(s); + unsigned int handshake_type = bs_get_byte(tls_record, 5); + if (handshake_type == 14) { /* Server Hello Done */ + bs_free(&tls_record); + CLOSE(s); + continue; + } + + /* Skip all records that aren't Server Key Exchanges (type 12). */ + while ((tls_record != NULL) && (bs_get_byte(tls_record, 5) != 12)) { + bs_free(&tls_record); + tls_record = getTLSHandshakeRecord(s); + handshake_type = bs_get_byte(tls_record, 5); + if (handshake_type == 14) { /* Server Hello Done */ + bs_free(&tls_record); + CLOSE(s); + continue; + } + } + + /* Error, so skip this group. */ + if (tls_record == NULL) { + bs_free(&tls_record); + CLOSE(s); + continue; + } + + /* If this Server Key Exchange does not have a named_curve (3) field, skip this group. */ + if (bs_get_byte(tls_record, 9) != 3) { + bs_free(&tls_record); + CLOSE(s); + continue; + } + + /* Check that the named_curve result is the group we requested. */ + uint16_t server_group_id = bs_get_byte(tls_record, 10) << 8 | bs_get_byte(tls_record, 11); + if (server_group_id != group_id) { + bs_free(&tls_record); + CLOSE(s); + continue; + } + + bs_free(&tls_record); + } + CLOSE(s); + + if (!printed_header) { + printf("\n %sServer Key Exchange Group(s):%s\n", COL_BLUE, RESET); + printed_header = 1; + } + + char *bits_color = RESET; + if (group_bit_strength < 112) + bits_color = COL_RED; + else + bits_color = COL_GREEN; + + char *printable_TLS_name = getPrintableTLSName(tls_version); + printf("%s %s%d%s bits %s%s%s\n", printable_TLS_name, bits_color, group_bit_strength, RESET, color, group_name, RESET); + printf_xml(" \n", printable_TLS_name, group_bit_strength, group_name, group_id); + } + } + + done: + CLOSE(s); + bs_free(&ciphersuite_list); + bs_free(&tls_extensions); + bs_free(&client_hello); + bs_free(&server_hello); + return ret; +} + +/* Enumerates all the signature algorithms supported by the server. */ +int testSignatureAlgorithms(struct sslCheckOptions *options) { + + struct signature_algorithm { + uint16_t sig_id; + char *sig_name; + char *color; + }; + +#define COL_PLAIN "" +#define BOGUS_SIG_ALG_ID 0xfdff /* Last un-assigned ID. */ + struct signature_algorithm signature_algorithms[] = { + {BOGUS_SIG_ALG_ID, "bogus", COL_RED}, /* Tests if the server is accepting all. */ + {0x0001, "rsa_pkcs1_nohash", COL_RED}, + {0x0002, "dsa_nohash", COL_RED}, + {0x0003, "ecdsa_nohash", COL_RED}, + {0x0101, "rsa_pkcs1_md5", COL_RED}, + {0x0102, "dsa_md5", COL_RED}, + {0x0103, "ecdsa_md5", COL_RED}, + {0x0201, "rsa_pkcs1_sha1", COL_RED}, + {0x0202, "dsa_sha1", COL_RED}, + {0x0203, "ecdsa_sha1", COL_RED}, + {0x0301, "rsa_pkcs1_sha224", COL_YELLOW}, + {0x0302, "dsa_sha224", COL_RED}, + {0x0303, "ecdsa_sha224", COL_YELLOW}, + {0x0401, "rsa_pkcs1_sha256", COL_PLAIN}, + {0x0402, "dsa_sha256", COL_RED}, + {0x0403, "ecdsa_secp256r1_sha256", COL_PLAIN}, + {0x0501, "rsa_pkcs1_sha384", COL_PLAIN}, + {0x0502, "dsa_sha384", COL_RED}, + {0x0503, "ecdsa_secp384r1_sha384", COL_PLAIN}, + {0x0601, "rsa_pkcs1_sha512", COL_PLAIN}, + {0x0602, "dsa_sha512", COL_RED}, + {0x0603, "ecdsa_secp521r1_sha512", COL_PLAIN}, + {0x0804, "rsa_pss_rsae_sha256", COL_PLAIN}, + {0x0805, "rsa_pss_rsae_sha384", COL_PLAIN}, + {0x0806, "rsa_pss_rsae_sha512", COL_PLAIN}, + {0x0807, "ed25519", COL_GREEN}, + {0x0808, "ed448", COL_GREEN}, + {0x0809, "rsa_pss_pss_sha256", COL_PLAIN}, + {0x080a, "rsa_pss_pss_sha384", COL_PLAIN}, + {0x080b, "rsa_pss_pss_sha512", COL_PLAIN}, + }; + + unsigned int printed_header = 0; + int ret = true, s = -1; + int test_versions[2] = {-1, -1}; + bs *client_hello = NULL, *ciphersuite_list = NULL, *tls_extensions = NULL, *server_hello = NULL; + + /* If TLSv1.3 is supported, test it first. */ + unsigned int index = 0; + if (options->tls13_supported) { + test_versions[index] = TLSv1_3; + index++; + } + + /* For TLSv1.2 and below, test the highest protocol version supported. */ + if (options->tls12_supported) + test_versions[index] = TLSv1_2; + else if (options->tls11_supported) + test_versions[index] = TLSv1_1; + else if (options->tls10_supported) + test_versions[index] = TLSv1_0; + + /* Loop through the one or two TLS versions to test. */ + for (index = 0; index < (sizeof(test_versions) / sizeof(int)); index++) { + int tls_version = test_versions[index]; + + /* If there's only one version to test... */ + if (tls_version == -1) + break; + + if (tls_version == TLSv1_3) { + /* Get all TLSv1.3 ciphersuites. */ + ciphersuite_list = makeCiphersuiteListTLS13All(); + } else + ciphersuite_list = makeCiphersuiteListAll(tls_version); + + + /* For each signature algorithm... */ + for (int i = 0; i < (sizeof(signature_algorithms) / sizeof(struct signature_algorithm)); i++) { + uint16_t sig_id = signature_algorithms[i].sig_id; + char *sig_name = signature_algorithms[i].sig_name; + char *color = signature_algorithms[i].color; + + + /* Make generic TLS extensions (with SNI, accepted EC point formats, etc). */ + tls_extensions = makeTLSExtensions(options, 0); + + if (tls_version == TLSv1_3) { + /* Extension: supported_groups */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x0a, // Extension: supported_groups (10) + 0x00, 0x16, // Extension Length (22) + 0x00, 0x14, // Supported Groups List Length (20) + 0x00, 0x17, // secp256r1 + 0x00, 0x19, // secp521r1 + 0x00, 0x18, // secp384r1 + 0x00, 0x1d, // X25519 + 0x00, 0x1e, // X448 + 0x01, 0x00, // FFDHE2048 + 0x01, 0x01, // FFDHE3072 + 0x01, 0x02, // FFDHE4096 + 0x01, 0x03, // FFDHE6144 + 0x01, 0x04, // FFDHE8192 + }, 26); + + /* Add key shares for X25519. */ + tlsExtensionAddDefaultKeyShare(tls_extensions); + + /* Add the supported_versions extension to signify we are using TLS v1.3. */ + tlsExtensionAddTLSv1_3(tls_extensions); + } + + /* Add the signature_algorithms extension. Only add the one group we are testing for. */ + bs_append_bytes(tls_extensions, (unsigned char []) { + 0x00, 0x0d, // Extension Type: signature_algorithms (13) + 0x00, 0x04, // Extension Length (4) + 0x00, 0x02, // Signature Hash Algorithms List Length (2) + }, 6); + bs_append_ushort(tls_extensions, sig_id); + + /* Update the TLS extensions length since we manually added to it. */ + tlsExtensionUpdateLength(tls_extensions); + + /* Create the Client Hello buffer using the ciphersuite list and TLS extensions. */ + client_hello = makeClientHello(options, tls_version, ciphersuite_list, tls_extensions); + + /* Free the TLS extensions since we're done with them. Note: we don't free the ciphersuite_list because we'll need them on the next loop. */ + bs_free(&tls_extensions); + + /* Now connect to the target server. */ + s = tcpConnect(options); + if (s == 0) { + ret = false; + goto done; + } + + /* Send the Client Hello message. */ + if (send(s, bs_get_bytes(client_hello), bs_get_len(client_hello), 0) <= 0) { + printf_error("send() failed while sending Client Hello: %d (%s)\n", errno, strerror(errno)); + ret = false; + goto done; + } + bs_free(&client_hello); + + server_hello = getServerHello(s); + CLOSE(s); + + /* This signature algorithm is not supported. */ + if (server_hello == NULL) + continue; + + bs_free(&server_hello); + + if (!printed_header) { + printf("\n %sServer Signature Algorithm(s):%s\n", COL_BLUE, RESET); + printed_header = 1; + } + + /* If the server accepted our bogus signature ID, then we can conclude that it will accept all of them (and not test any further). Some servers in the wild do this for some reason... */ + if (sig_id == BOGUS_SIG_ALG_ID) { + printf("%s%s Server accepts all signature algorithms.%s\n", getPrintableTLSName(tls_version), COL_YELLOW, RESET); + goto done; + } else { + printf("%s %s%s%s\n", getPrintableTLSName(tls_version), color, sig_name, RESET); + printf_xml(" \n", getPrintableTLSName(tls_version), sig_name, sig_id); + } + } + } + + done: + CLOSE(s); + bs_free(&ciphersuite_list); + bs_free(&tls_extensions); + bs_free(&client_hello); + bs_free(&server_hello); + return ret; +} + /* MinGW doesn't have a memmem() implementation. */ #ifdef _WIN32 diff --git a/sslscan.h b/sslscan.h index be9a63e..7d9b4ee 100644 --- a/sslscan.h +++ b/sslscan.h @@ -37,6 +37,8 @@ #ifndef HAVE_SSLSCAN_H_ #define HAVE_SSLSCAN_H_ +#include "missing_ciphersuites.h" + // Defines... #define false 0 #define true 1 @@ -48,6 +50,7 @@ #define BUFFERSIZE 1024 +// For options.sslVersion field. #define ssl_all 0 #define ssl_v2 1 #define ssl_v3 2 @@ -55,6 +58,19 @@ #define tls_v10 4 #define tls_v11 5 #define tls_v12 6 +#define tls_v13 7 + +// For functions that take a tls_version argument. +#define TLSv1_0 0 +#define TLSv1_1 1 +#define TLSv1_2 2 +#define TLSv1_3 3 + +/* We must maintain our own list of TLSv1.3-specific ciphersuites here, because SSL_CTX_get_ciphers() will *always* return TLSv1.2 ciphersuites, even when SSL_CTX_set_min_proto_version() and SSL_CTX_set_max_proto_version() are used. This is confirmed by an OpenSSL developer here: https://github.com/openssl/openssl/issues/7196#issuecomment-420575202 */ +#define TLSV13_CIPHERSUITES "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256" + +/* Cipherlist for TLSv1.2 and below that corresponds to all available ciphersuites. */ +#define CIPHERSUITE_LIST_ALL "ALL:COMPLEMENTOFALL" // Macros for various outputs #define printf(format, ...) if (!xml_to_stdout) fprintf(stdout, format, ##__VA_ARGS__) @@ -62,6 +78,18 @@ #define printf_xml(format, ...) if (options->xmlOutput) fprintf(options->xmlOutput, format, ##__VA_ARGS__) #define printf_verbose(format, ...) if (options->verbose) printf(format, ##__VA_ARGS__) +/* Calls close() on a file descriptor, then sets it to zero to prevent accidental re-use. */ +#define CLOSE(fd) { if ((fd) != -1) { close((fd)); (fd) = -1; } } + +/* Calls free() on a pointer, then explicitly sets it to NULL to avoid use-after-free. */ +#define FREE(ptr) { free((ptr)); (ptr) = NULL; } + +/* Frees an SSL pointer, and explicitly sets it to NULL to avoid use-after-free. */ +#define FREE_SSL(ssl) { if ((ssl) != NULL) { SSL_free((ssl)); (ssl) = NULL; } } + +/* Frees a SSL_CTX pointer, and explicitly sets it to NULL to avoid use-after-free. */ +#define FREE_CTX(ctx) { if ((ctx) != NULL) { SSL_CTX_free((ctx)); (ctx) = NULL; } } + // Colour Console Output... // Always better to do "const char RESET[] = " because it saves relocation records. // Default colours were hard to read on Windows, so use lighter ones @@ -104,7 +132,7 @@ struct sslCipher { // Cipher Properties... const char *name; - char *version; + const char *version; int bits; char description[512]; const SSL_METHOD *sslMethod; @@ -129,6 +157,8 @@ struct sslCheckOptions int fallback; int compression; int heartbleed; + int groups; + int signature_algorithms; int starttls_ftp; int starttls_imap; int starttls_irc; @@ -167,6 +197,12 @@ struct sslCheckOptions char *clientCertsFile; char *privateKeyFile; char *privateKeyPassword; + + // TLS versions supported by the server. + unsigned int tls10_supported; + unsigned int tls11_supported; + unsigned int tls12_supported; + unsigned int tls13_supported; }; // store renegotiation test data @@ -176,6 +212,79 @@ struct renegotiationOutput int secure; }; +/* For OCSP processing. Taken from crypto/ocsp/ocsp_local.h in OpenSSL, which does not seem to be normally exposed externally. */ +struct ocsp_response_st { + ASN1_ENUMERATED *responseStatus; + OCSP_RESPBYTES *responseBytes; +}; + +struct ocsp_resp_bytes_st { + ASN1_OBJECT *responseType; + ASN1_OCTET_STRING *response; +}; + +struct ocsp_responder_id_st { + int type; + union { + X509_NAME *byName; + ASN1_OCTET_STRING *byKey; + } value; +}; +typedef struct ocsp_responder_id_st OCSP_RESPID; + +struct ocsp_response_data_st { + ASN1_INTEGER *version; + OCSP_RESPID responderId; + ASN1_GENERALIZEDTIME *producedAt; + STACK_OF(OCSP_SINGLERESP) *responses; + STACK_OF(X509_EXTENSION) *responseExtensions; +}; +typedef struct ocsp_response_data_st OCSP_RESPDATA; + +struct ocsp_basic_response_st { + OCSP_RESPDATA tbsResponseData; + X509_ALGOR signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; +}; + +struct ocsp_single_response_st { + OCSP_CERTID *certId; + OCSP_CERTSTATUS *certStatus; + ASN1_GENERALIZEDTIME *thisUpdate; + ASN1_GENERALIZEDTIME *nextUpdate; + STACK_OF(X509_EXTENSION) *singleExtensions; +}; + +struct ocsp_cert_status_st { + int type; + union { + ASN1_NULL *good; + OCSP_REVOKEDINFO *revoked; + ASN1_NULL *unknown; + } value; +}; + +struct ocsp_revoked_info_st { + ASN1_GENERALIZEDTIME *revocationTime; + ASN1_ENUMERATED *revocationReason; +}; + +struct ocsp_cert_id_st { + X509_ALGOR hashAlgorithm; + ASN1_OCTET_STRING issuerNameHash; + ASN1_OCTET_STRING issuerKeyHash; + ASN1_INTEGER serialNumber; +}; + +#define BS_DEFAULT_NEW_SIZE 256 /* The starting size of the buffer when bs_new() is used. */ +struct _bs { + unsigned char *buf; + size_t size; /* The size of the allocated buffer. */ + size_t len; /* The number of bytes currently in the buffer. */ +}; +typedef struct _bs bs; /* Stands for 'byte string'. */ + /* We redefine these so that we can run correctly even if the vendor gives us * a version of OpenSSL that does not match its header files. (Apple: I am * looking at you.) @@ -188,17 +297,44 @@ struct renegotiationOutput #endif // Utilities +void bs_new(bs **); +void bs_new_size(bs **, size_t); +void bs_free(bs **); +void bs_append_bytes(bs *, unsigned char *, size_t); +void bs_append_uint32_t(bs *, uint32_t); +void bs_append_ushort(bs *, unsigned short); +void bs_append_bs(bs *, bs *); +size_t bs_get_len(bs *); +size_t bs_get_size(bs *); +unsigned char *bs_get_bytes(bs *); +unsigned char bs_get_byte(bs *, size_t); +void bs_set_byte(bs *, size_t, unsigned char); +void bs_set_ushort(bs *b, size_t offset, unsigned short length); +int bs_read_socket(bs *b, int s, size_t num_bytes); +unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsigned int tls_version); +SSL_CTX *CTX_new(const SSL_METHOD *method); int fileExists(char *); +void findMissingCiphers(); +char *getPrintableTLSName(unsigned int tls_version); +bs *getServerHello(int s); +bs *makeCiphersuiteListAll(unsigned int tls_version); +bs *makeCiphersuiteListTLS13All(); +bs *makeCiphersuiteListMissing(unsigned int tls_version); +bs *makeClientHello(struct sslCheckOptions *options, unsigned int version, bs *ciphersuite_list, bs *tls_extensions); +bs *makeTLSExtensions(struct sslCheckOptions *options, unsigned int include_signature_algorithms); +void markFoundCiphersuite(unsigned short server_cipher_id, unsigned int tls_version); +int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent); +static int ocsp_resp_cb(SSL *s, void *arg); void readLine(FILE *, char *, int); -ssize_t sendString(int, const char[]); int readOrLogAndClose(int, void *, size_t, const struct sslCheckOptions *); -const char *printableSslMethod(const SSL_METHOD *); -const char *SSL_ERR_to_string (int sslerr); +char *resolveCipherID(unsigned short cipher_id, int *cipher_bits); static int password_callback(char *, int, int, void *); +const char *printableSslMethod(const SSL_METHOD *); +ssize_t sendString(int, const char[]); int ssl_print_tmp_key(struct sslCheckOptions *, SSL *s); -static int ocsp_resp_cb(SSL *s, void *arg); -int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent); - +void tlsExtensionAddDefaultKeyShare(bs *tls_extensions); +void tlsExtensionAddTLSv1_3(bs *tls_extensions); +void tlsExtensionUpdateLength(bs *tls_extensions); int tcpConnect(struct sslCheckOptions *); // Tests @@ -213,16 +349,20 @@ int testRenegotiation(struct sslCheckOptions *, const SSL_METHOD *); int testfallback(struct sslCheckOptions *, const SSL_METHOD *); #endif int testHeartbleed(struct sslCheckOptions *, const SSL_METHOD *); +int testSupportedGroups(struct sslCheckOptions *options); +int testSignatureAlgorithms(struct sslCheckOptions *options); int testCipher(struct sslCheckOptions *, const SSL_METHOD *); +int testMissingCiphers(struct sslCheckOptions *options, unsigned int version); int testProtocolCiphers(struct sslCheckOptions *, const SSL_METHOD *); int testConnection(struct sslCheckOptions *); int testHost(struct sslCheckOptions *); - int loadCerts(struct sslCheckOptions *); int checkCertificateProtocols(struct sslCheckOptions *, const SSL_METHOD *); int checkCertificate(struct sslCheckOptions *, const SSL_METHOD *); int showCertificate(struct sslCheckOptions *); +int runSSLv2Test(struct sslCheckOptions *options); +int runSSLv3Test(struct sslCheckOptions *options); #endif /* vim :set ts=4 sw=4 sts=4 et : */ diff --git a/tools/iana_tls_ciphersuite_parser.py b/tools/iana_tls_ciphersuite_parser.py new file mode 100755 index 0000000..be06258 --- /dev/null +++ b/tools/iana_tls_ciphersuite_parser.py @@ -0,0 +1,96 @@ +#!/usr/bin/python3 + +# +# Copyright (C) 2019 Joe Testa +# +# This tool will parse the list of TLS ciphersuites from IANA +# (https://www.iana.org/assignments/tls-parameters/tls-parameters.xml) into a C-struct +# for use in missing_ciphersuites.h. +# + +import csv, sys +from datetime import date + + +# We must be given a path to a CSV file with the ciphersuites. It can be obtained from +# . +if len(sys.argv) != 2: + print("\nUsage: %s tls_ciphers.csv\n\nHint: copy the TLS table in CSV format from .\n" % sys.argv[0]) + exit(0) + +csv_file = sys.argv[1] + +print("/* Auto-generated by %s on %s. */" % (sys.argv[0], date.today().strftime("%B %d, %Y"))) +print("struct missing_ciphersuite missing_ciphersuites[] = {") +with open(csv_file, 'r') as f: + reader = csv.reader(f) + for row in reader: + id = row[0] + cipher_name = row[1] + + # Skip the header. + if '0x' not in id: + continue + + # Skip reserved or unassigned ranges. Also skip SCSV ciphers. + if ('Reserved' in cipher_name) or ('Unassigned' in cipher_name) or ('TLS_FALLBACK_SCSV' in cipher_name) or ('TLS_EMPTY_RENEGOTIATION_INFO_SCSV' in cipher_name): + continue + + # Convert '0xC0,0x87' to '0xC087' + parsed_id = id[0:4] + id[7:9] + if len(parsed_id) != 6: + print("Error: parsed ID is not length 6: %s" % parsed_id) + exit -1 + + # Make an educated guess of the cipher's bit strength based on its name. + bits = -1 + if 'AES_128' in cipher_name: + bits = 128 + elif 'AES_256' in cipher_name: + bits = 256 + elif 'CHACHA20' in cipher_name: + bits = 256 + elif 'CAMELLIA_128' in cipher_name: + bits = 128 + elif 'CAMELLIA_256' in cipher_name: + bits = 256 + elif 'ARIA_128' in cipher_name: + bits = 128 + elif 'ARIA_256' in cipher_name: + bits = 256 + elif '3DES' in cipher_name: + bits = 112 + elif 'DES40' in cipher_name: + bits = 40 + elif '_DES_' in cipher_name: + bits = 56 + elif 'RC4_128' in cipher_name: + bits = 128 + elif 'RC4_40' in cipher_name: + bits = 40 + elif 'IDEA' in cipher_name: + bits = 128 + elif '_RC2_' in cipher_name: + bits = 40 + elif 'GOSTR341112_256' in cipher_name: + bits = 256 + elif '_SM4_' in cipher_name: # See http://www.gmbz.org.cn/upload/2018-04-04/1522788048733065051.pdf + bits = 128 + + print(' {%s, "%s", %d, VALL, 0},' % (parsed_id, cipher_name, bits)) + + # These ciphers are reserved for private use. Kind of like the 10.0.0.0/8 IPv4 + # addresses. + print("\n /* The ciphers below are reserved for private use (see RFC8446). */") + for i in range(0, 256): + low_byte = hex(i)[2:].upper() + if len(low_byte) == 1: + low_byte = '0' + low_byte + + parsed_id = '0xFF' + low_byte + cipher_name = 'PRIVATE_CIPHER_%d' % i + bits = -1 + print(' {%s, "%s", %d, VALL, 0},' % (parsed_id, cipher_name, bits)) + +print("};") +exit 0 diff --git a/tools/iana_tls_supported_groups_parser.py b/tools/iana_tls_supported_groups_parser.py new file mode 100755 index 0000000..c766c30 --- /dev/null +++ b/tools/iana_tls_supported_groups_parser.py @@ -0,0 +1,126 @@ +#!/usr/bin/python3 + +# +# Copyright (C) 2019 Joe Testa +# +# This tool will parse the list of TLS supported groups from IANA +# (https://www.iana.org/assignments/tls-parameters/tls-parameters-8.csv) into a C-struct +# for use in testSupportedGroups(). +# + +import csv, sys +from datetime import date + + +# We must be given a path to a CSV file with the groups. It can be obtained from +# . +if len(sys.argv) != 2: + print("\nUsage: %s tls_ciphers.csv\n\nHint: copy the TLS table in CSV format from .\n" % sys.argv[0]) + exit(0) + +csv_file = sys.argv[1] + +print() +print(" /* Auto-generated by %s on %s. */" % (sys.argv[0], date.today().strftime("%B %d, %Y"))) +print('#define COL_PLAIN ""') +print('#define NID_TYPE_NA 0 /* Not Applicable (i.e.: X25519/X448) */') +print('#define NID_TYPE_ECDHE 1 /* For ECDHE curves (sec*, P-256/384-521) */') +print('#define NID_TYPE_DHE 2 /* For ffdhe* */') +print(" /* Bit strength of DHE 2048 and 3072-bit moduli is taken directly from NIST SP 800-57 pt.1, rev4., pg. 53; DHE 4096, 6144, and 8192 are estimated using that document. */") +print(" struct group_key_exchange group_key_exchanges[] = {") +with open(csv_file, 'r') as f: + reader = csv.reader(f) + for row in reader: + id = row[0] + group_name = row[1] + reference = row[4] + + # Skip the header. + try: + int(id) + except ValueError as e: + continue + + id = int(id) + + # Skip reserved or unassigned IDs. + if group_name in ('Reserved', 'Unassigned'): + continue + + # The Reference field looks like "[RFC1234]", "[draft-blah-blah]", or "[RFC-ietf-tls-blah-02]". Skip all rows that aren't of the "[RFC1234]" variety. + reference = reference[1:] + rt_bracket_pos = reference.find(']') + if rt_bracket_pos == -1: + print("Warning: can't parse reference: %s" % reference) + else: + reference = reference[3:rt_bracket_pos] + + try: + int(reference) + except ValueError as e: + continue + + bits = 0 + nid = "NID_x" + nid_type = "NID_TYPE_x" + key_exchange_len = 0 + color = "COL_PLAIN" + if group_name.startswith('sec'): + bits = int(group_name[4:-2]) / 2 + nid = "NID_%s" % group_name + nid_type = "NID_TYPE_ECDHE" + if group_name == "secp192r1": + nid = "NID_X9_62_prime192v1" + elif group_name == "secp256r1": + nid = "NID_X9_62_prime256v1" + group_name += ' (NIST P-256)' + elif group_name == "secp256k1": + color = "COL_GREEN" # This is the very well-tested Bitcoin curve. + elif group_name == "secp384r1": + group_name += ' (NIST P-384)' + elif group_name == "secp521r1": + group_name += ' (NIST P-521)' + elif group_name.startswith('brainpoolP'): + bits = int(group_name[10:-2]) / 2 + nid = "NID_%s" % group_name + nid_type = "NID_TYPE_ECDHE" + elif group_name in ('x25519', 'x448'): + color = "COL_GREEN" + nid = "-1" + nid_type = "NID_TYPE_NA" + if group_name == 'x25519': + bits = 128 + key_exchange_len = 32 + elif group_name == 'x448': + bits = 224 + key_exchange_len = 56 + elif group_name.startswith('ffdhe'): + # Bit strength of DHE 2048 and 3072-bit moduli is taken directly from NIST SP 800-57 pt.1, rev4., pg. 53; DHE 4096, 6144, and 8192 are estimated using that document. + if group_name == 'ffdhe2048': + bits = 112 + key_exchange_len = 256 + elif group_name == 'ffdhe3072': + bits = 128 + key_exchange_len = 384 + elif group_name == 'ffdhe4096': + bits = 150 + key_exchange_len = 512 + elif group_name == 'ffdhe6144': + bits = 175 + key_exchange_len = 768 + elif group_name == 'ffdhe8192': + bits = 192 + key_exchange_len = 1024 + nid = "NID_%s" % group_name + nid_type = "NID_TYPE_DHE" + elif group_name.startswith('arbitrary_'): # Skip these two. + continue + + if bits < 112: + color = "COL_RED" + + print(' {0x%04x, "%s", %d, %s, %s, %s, %d},' % (id, group_name, bits, color, nid, nid_type, key_exchange_len)) + +print(" };") +print() +exit(0)