diff --git a/bench-scripts/README.md b/bench-scripts/README.md index e91f1901..5fbb2013 100644 --- a/bench-scripts/README.md +++ b/bench-scripts/README.md @@ -84,6 +84,21 @@ all siege tests connect to HA-proxy via, which then establishes SSL connection towards httpterm [10] server. To collect performance data The siege client executes requests which fetch 1k of data from httpterm server. +## OpenSSL Forks + +This test builds OpenSSL forks and uses perftools to benchmark those forks. +The list of perftools which can run with forks: + randbytes + rsasign + handshake + sslnew + x509storeissuer + evp_setpeer (only for some keys) + +The bench_config_forks.sh script builds and install libraries. It also builds +perftools for each OpenSSL fork library. The script also builds openssl-master. +The bench_run_forks.sh runs tests and plots results as .png files. + ## Build requirements Requirements for ubuntu are the following: diff --git a/bench-scripts/bench_config_forks.sh b/bench-scripts/bench_config_forks.sh new file mode 100755 index 00000000..9d21b52e --- /dev/null +++ b/bench-scripts/bench_config_forks.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env ksh +# +# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# + +set -x + +. ./common_util.sh + +INSTALL_ROOT=${BENCH_INSTALL_ROOT:-"/tmp/bench.binaries"} +RESULT_DIR=${BENCH_RESULTS:-"${INSTALL_ROOT}/results"} +WORKSPACE_ROOT=${BENCH_WORKSPACE_ROOT:-"/tmp/bench.workspace"} +MAKE_OPTS=${BENCH_MAKE_OPTS} +CFLAGS_SAVE=${CFLAGS} + +WOLFSSL_VERSION=5.8.2 +LIBRESSL_VERSION=4.2.1 +OPENSSL_VERSION=master + +function build_perftools { + # + # when testing changes for C-code or CMakeFileList.txt + # you must change link to repository, so script pulls + # modified sources + # + typeset PERFTOOLS='https://github.com/openssl/perftools' + + cd ${WORKSPACE_ROOT} || exit 1 + # + # you may also need to change clone command to + # checkout correct branch. + # + git clone ${PERFTOOLS} || exit 1 + cd perftools/source || exit 1 + + cmake -S ${WORKSPACE_ROOT}/perftools/source \ + -B ${INSTALL_ROOT}/build.openssl-${OPENSSL_VERSION} \ + -DOPENSSL_CONFIG_MODE=1 \ + -DCMAKE_PREFIX_PATH=${INSTALL_ROOT}/openssl-${OPENSSL_VERSION} \ + -DCMAKE_PREFIX_PATH=${INSTALL_ROOT}/openssl-${OPENSSL_VERSION} || exit 1 + cmake --build ${INSTALL_ROOT}/build.openssl-${OPENSSL_VERSION} || exit 1 + + cmake -S ${WORKSPACE_ROOT}/perftools/source \ + -B ${INSTALL_ROOT}/build.wolfssl-${WOLFSSL_VERSION} \ + -DWITH_OPENSSL_FORK=1 \ + -DCMAKE_PREFIX_PATH=${INSTALL_ROOT}/wolfssl-${WOLFSSL_VERSION} || exit 1 + cmake --build ${INSTALL_ROOT}/build.wolfssl-${WOLFSSL_VERSION} || exit 1 + + cmake -S ${WORKSPACE_ROOT}/perftools/source \ + -B ${INSTALL_ROOT}/build.libressl-${LIBRESSL_VERSION} \ + -DWITH_OPENSSL_FORK=1 \ + -DCMAKE_PREFIX_PATH=${INSTALL_ROOT}/libressl-${LIBRESSL_VERSION} || exit 1 + cmake --build ${INSTALL_ROOT}/build.libressl-${LIBRESSL_VERSION} || exit 1 + + cmake -S . -B $BENCH_INSTALL_ROOT/build.boringssl/ \ + -DCMAKE_PREFIX_PATH=$BENCH_INSTALL_ROOT/boringssl \ + -DWITH_OPENSSL_FORK=1 || exit 1 + cmake --build ${INSTALL_ROOT}/build.boringssl || exit 1 + + cmake -S . -B $BENCH_INSTALL_ROOT/build.aws-lc/ \ + -DCMAKE_PREFIX_PATH=$BENCH_INSTALL_ROOT/aws-lc \ + -DWITH_OPENSSL_FORK=1 || exit 1 + cmake --build ${INSTALL_ROOT}/build.aws-lc || exit 1 +} + +install_openssl ${OPENSSL_VERSION} + +# +# enable WolfSSL's compatibility layer with OpenSSL. +# another option is to use ./configure --enable-opensslextra +# see: https://www.wolfssl.com/documentation/manuals/wolfssl/chapter13.html +# +CFLAGS="${CFLAGS} -DOPENSSL_EXTRA -DOPENSSL_ALL" +install_wolfssl ${WOLFSSL_VERSION} +CFLAGS=${CFLAGS_SAVE} + +install_libressl ${LIBRESSL_VERSION} + +install_boringssl + +install_aws_lc + +build_perftools diff --git a/bench-scripts/bench_run_forks.sh b/bench-scripts/bench_run_forks.sh new file mode 100755 index 00000000..1e7925c1 --- /dev/null +++ b/bench-scripts/bench_run_forks.sh @@ -0,0 +1,319 @@ +#!/usr/bin/env ksh +# +# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# + +set -x + +. ./common_util.sh + +INSTALL_ROOT=${BENCH_INSTALL_ROOT:-"/tmp/bench.binaries"} +RESULT_DIR=${BENCH_RESULTS:-"${INSTALL_ROOT}/results"} +WORKSPACE_ROOT=${BENCH_WORKSPACE_ROOT:-"/tmp/bench.workspace"} +MAKE_OPTS=${BENCH_MAKE_OPTS} +CFLAGS_SAVE=${CFLAGS} +CERTDIR=${WORKSPACE_ROOT}/openssl-master/test/certs + +function run_randbytes { + typeset FORKDIR=${1} + typeset THREAD_COUNT=${2} + typeset RANDBYTES=${FORKDIR}/randbytes + typeset FORKNAME=`basename ${FORKDIR} | sed -e 's/build\.//g'` + typeset RESULT=${RESULT_DIR}/${FORKNAME}-randbytes-${THREAD_COUNT}.out + + ${RANDBYTES} ${THREAD_COUNT} > ${RESULT} +} + +function run_rsasign { + typeset FORKDIR=${1} + typeset THREAD_COUNT=${2} + typeset RANDBYTES=${FORKDIR}/rsasign + typeset FORKNAME=`basename ${FORKDIR} | sed -e 's/build\.//g'` + typeset RESULT=${RESULT_DIR}/${FORKNAME}-rsasign-${THREAD_COUNT}.out + + ${RANDBYTES} ${THREAD_COUNT} > ${RESULT} +} + +function run_handshake { + typeset FORKDIR=${1} + typeset THREAD_COUNT=${2} + typeset HANDSHAKE=${FORKDIR}/handshake + typeset FORKNAME=`basename ${FORKDIR} | sed -e 's/build\.//g'` + typeset RESULT=${RESULT_DIR}/${FORKNAME}-handshake-${THREAD_COUNT}.out + + case ${FORKDIR} in + boringssl) + echo -n 'handshake does not work on boring: ?' > ${RESULT} + ;; + aws-lc) + echo -n 'handshake does not work on aws: ?' > ${RESULT} + ;; + *) + ${HANDSHAKE} ${CERTDIR} ${THREAD_COUNT} > ${RESULT} + ;; + esac +} + +function run_sslnew { + typeset FORKDIR=${1} + typeset THREAD_COUNT=${2} + typeset SSLNEW=${FORKDIR}/sslnew + typeset FORKNAME=`basename ${FORKDIR} | sed -e 's/build\.//g'` + typeset RESULT=${RESULT_DIR}/${FORKNAME}-sslnew-${THREAD_COUNT}.out + + ${SSLNEW} ${THREAD_COUNT} > ${RESULT} +} + +function run_x509storeissuer { + typeset FORKDIR=${1} + typeset THREAD_COUNT=${2} + typeset X509STOREISSUER=${FORKDIR}/x509storeissuer + typeset FORKNAME=`basename ${FORKDIR} | sed -e 's/build\.//g'` + typeset RESULT=${RESULT_DIR}/${FORKNAME}-x509storeissuer-${THREAD_COUNT}.out + + ${X509STOREISSUER} ${CERTDIR} ${THREAD_COUNT} > ${RESULT} +} + +function run_evp_setpeer { + typeset FORKDIR=${1} + typeset THREAD_COUNT=${2} + typeset EVP_SETPEER=${FORKDIR}/evp_setpeer + typeset FORKNAME=`basename ${FORKDIR} | sed -e 's/build\.//g'` + typeset RESULT_BASE=${RESULT_DIR}/${FORKNAME}-evp_setpeer + typeset KEY='' + typeset RESULT='' + + for KEY in dh ec256 ec521 x25519 ; do + RESULT=${RESULT_BASE}-${KEY}-${THREAD_COUNT}.out + ${EVP_SETPEER} -k ${KEY} ${THREAD_COUNT} > ${RESULT} + done +} + +function run_writeread { + typeset FORKDIR=${1} + typeset THREAD_COUNT=${2} + typeset WRITEREAD=${FORKDIR}/writeread + typeset FORKNAME=`basename ${FORKDIR} | sed -e 's/build\.//g'` + typeset RESULT=${RESULT_DIR}/${FORKNAME}-writeread-${THREAD_COUNT}.out + + ${WRITEREAD} ${CERTDIR} ${THREAD_COUNT} > ${RESULT} +} + +function yield_tests { + echo -n 'randbytes ' + echo -n 'rsasign ' + echo -n 'handshake ' + echo -n 'sslnew ' + echo -n 'x509storeissuer ' + echo -n 'evp_setpeer-dh ' + echo -n 'evp_setpeer-ec256 ' + echo -n 'evp_setpeer-ec521 ' + echo -n 'evp_setpeer-x25519 ' + echo 'writeread' +} + +function get_description { + typeset TEST=${1} + typeset SELECT_LINE=${2} + # + # tools work reliably for openssl master tests, some tests + # fail (are not implemented) for 3rd party libraries. + # therefore the function uses openssl-master to read + # bench mark description from result file. + # + typeset OPENSSL_RESULT=${RESULT_DIR}/openssl-master-${TEST}-1.out + + # + # result for handshake test contains two lines: + # Average time per handshake: .... + # Handshakes per second: ... + # depending on LINE the function returns either the first (1) + # or the last (2) + # + if [[ ${SELECT_LINE} -eq 1 ]] ; then + head -n 1 ${OPENSSL_RESULT} | sed -e 's/:.*$//g' + else + tail -n 1 ${OPENSSL_RESULT} | sed -e 's/:.*$//g' + fi +} + +function get_value { + typeset RESULT_FILE=${1} + typeset SELECT_LINE=${2} + + if [[ -s ${RESULT_FILE} ]] ; then + # + # handshake test for boringssl drops 'Unexpected error...' + # message to result file. + # + grep -e 'Unexpected error' ${RESULT_FILE} > /dev/null + if [[ $? -eq 0 ]] ; then + echo -n '?' + else + # + # chop off description and 'us' time unit so the only thing which + # remains is decimal number. + # + if [[ ${SELECT_LINE} -eq 1 ]] ; then + head -n 1 ${RESULT_FILE} | sed -e 's/^.*://g' -e 's/us$//g' + else + tail -n 1 ${RESULT_FILE} | sed -e 's/^.*://g' -e 's/us$//g' + fi + fi + else + # + # if file is empty, then method/cipher is not implemented + # by 3rd party library + # + echo -n '?' + fi +} + +# +# Test produces file which naming convention +# reads as follows: +# fork-test-threads.out +# the 'fork' component is determined from install root +# where each tool set is installed as build.${fork}. +# Using sed the function can safely determined fork name +# even if the name reads as libressl-4.2.1. +# +# the test component also may contain '-', however script +# keeps test names in `yield_tests` function. The thread +# count is also determined taking the similar approach. +# +# all result files report an average time single benchmark +# operation takes. Time is reported in uSec. +# +# The only exception here is handshake test which reports +# two numbers: +# average handshake duration (line 1) +# number of handshake per second (line 2) +# +function merge_result { + typeset TEST=${1} + typeset SELECT_LINE=${2} + typeset THREAD_COUNT='' + typeset FORK='' + typeset LINE='' + typeset OUTPUT_FILE='' + typeset INPUT_FILE='' + + if [[ ${TEST} = 'handshake' ]] ; then + OUTPUT_FILE=${RESULT_DIR}/${TEST}-${SELECT_LINE}.merged + else + OUTPUT_FILE=${RESULT_DIR}/${TEST}.merged + fi + get_description ${TEST} ${SELECT_LINE} > ${OUTPUT_FILE} + printf 'line-no.\tThreads' >> ${OUTPUT_FILE} + for FORK in ${INSTALL_ROOT}/build.* ; do + FORK=`basename ${FORK} | sed -e 's/build\.//g'` + printf "\t${FORK}" >> ${OUTPUT_FILE} + done + printf '\n' >> ${OUTPUT_FILE} + LINE=1 + for THREAD_COUNT in `procs` ; do + printf "${LINE}\t${THREAD_COUNT}" >> ${OUTPUT_FILE} + for FORK in ${INSTALL_ROOT}/build.* ; do + FORK=`basename ${FORK} | sed -e 's/build\.//g'` + INPUT_FILE=${RESULT_DIR}/${FORK}-${TEST}-${THREAD_COUNT}.out + printf "\t`get_value ${INPUT_FILE} ${SELECT_LINE}`" >> ${OUTPUT_FILE} + done + printf '\n' >> ${OUTPUT_FILE} + LINE=$(( ${LINE} + 1)) + done +} + +# +# the results for handshake test contain +# two numbers: +# average number of handshakes per second +# handshakes per sec +# hence there is extra call outside of loop to call +# to merge results for completed handshakes. +# +function merge_results { + typeset TEST='' + + for TEST in `yield_tests` ; do + merge_result ${TEST} 1 + done + + merge_result 'handshake' 2 +} + +function plot_result { + typeset DATA_FILE=${1}.data + typeset OUT_FILE=${2} + typeset YLABEL=${3} + typeset TITLE=`head -n 1 ${1}` + + # + # chop off the fist line (title) + # + tail -n +2 ${1} > ${DATA_FILE} + gnuplot << EOF +set title "${TITLE}" +set grid lt 0 lw 1 ls 1 lc rgb "#d7d7d7" +set xlabel "Number of threads" +set ylabel "${YLABEL}" +set terminal pngcairo size 800,400 background rgb "#f8f8f8" +set output "${OUT_FILE}" +set key autotitle columnhead outside +set auto x +set style data histogram +set style histogram cluster gap 1 +set style fill solid border -1 +set datafile missing '?' +set title noenhanced +set boxwidth 0.9 +plot \ + "${DATA_FILE}" using 3:xticlabels(2) ti col, \ + "${DATA_FILE}" using 4 ti col, \ + "${DATA_FILE}" using 5 ti col, \ + "${DATA_FILE}" using 6 ti col, \ + "${DATA_FILE}" using 7 ti col +EOF + rm ${DATA_FILE} +} + +function plot_results { + typeset RESULT='' + typeset RESULT_BASENAME + typeset OUTFILE='' + typeset YLABEL='' + + for RESULT in ${RESULT_DIR}/*.merged ; do + RESULT_BASENAME=`basename ${RESULT}` + if [[ ${RESULT_BASENAME} = 'handshake-2.merged' ]] ; then + YLABEL='ops per sec.' + else + YLABEL='single op. in uSec' + fi + OUTFILE=`echo ${RESULT} | sed -e 's/merged/png/g'` + plot_result ${RESULT} ${OUTFILE} "${YLABEL}" + echo ${OUTFILE} + done +} + +mkdir -p ${RESULT_DIR} + +for THREAD_COUNT in `procs` ; do + for FORK in ${INSTALL_ROOT}/build.* ; do + run_randbytes ${FORK} ${THREAD_COUNT} + run_rsasign ${FORK} ${THREAD_COUNT} + run_handshake ${FORK} ${THREAD_COUNT} + run_sslnew ${FORK} ${THREAD_COUNT} + run_x509storeissuer ${FORK} ${THREAD_COUNT} + run_evp_setpeer ${FORK} ${THREAD_COUNT} + run_writeread ${FORK} ${THREAD_COUNT} + done +done + +merge_results +plot_results diff --git a/bench-scripts/common_util.sh b/bench-scripts/common_util.sh index f58882ed..48537f49 100644 --- a/bench-scripts/common_util.sh +++ b/bench-scripts/common_util.sh @@ -164,6 +164,7 @@ function install_wolfssl { if [[ -z ${HAPROXY_OPTS} ]] ; then ./configure --prefix="${INSTALL_ROOT}/${DIRNAME}" \ + --enable-dtls \ --enable-nginx || exit 1 else ./configure --prefix="${INSTALL_ROOT}/${DIRNAME}" \ @@ -200,7 +201,27 @@ function install_boringssl { cd "${WORKSPACE_ROOT}" mkdir -p "${BORING_NAME}" cd "${BORING_NAME}" - git clone "${BORING_REPO}" --depth 1 . || exit 1 + # + # note we are cloning a master branch of boringssl. + # if things are unfortunate the branch may not build + # if it is the case, then be ready to modify the + # command here to clone version which builds. + # It looks like boringssl tides up its releases + # with google chrome: + # https://boringssl.googlesource.com/boringssl + # using a tag from list above should help you to get + # a stable release. There is also this list on + # github which may also help: + # https://github.com/google/boringssl/releases + # + # example checks out: + # git clone "${BORING_REPO}" . || exit 1 + # git checkout 0.20260211.0 || exit 1 + # release From Feb 11th 20226 should be the same + # to what's found here: + # https://github.com/google/boringssl/releases/tag/0.20260211.0 + # + git clone --depth 1 "${BORING_REPO}" . || exit 1 # # we need to install libdecrepit.so so mod_ssl can use # base64 BIO file stream diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 17c7f035..8a1d186d 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -114,6 +114,8 @@ # [1] https://cmake.org/cmake/help/v4.0/release/4.0.html#other-changes # +option(WITH_OPENSSL_FORK "WITH_OPENSSL_FORK" 0) + cmake_minimum_required(VERSION 3.10) project(perf-tools) include(CheckSymbolExists) @@ -136,7 +138,6 @@ if(OPENSSL_CONFIG_MODE) else() unset(OPENSSL_CONFIG_MODE) endif() -find_package(OpenSSL REQUIRED ${OPENSSL_CONFIG_MODE}) add_library(perf perflib/perfhelper.c perflib/perfsslhelper.c perflib/threads.c perflib/time.c) @@ -153,10 +154,59 @@ if(WIN32) endif() target_include_directories(perf PUBLIC "${PROJECT_SOURCE_DIR}") -target_link_libraries(perf PUBLIC OpenSSL::SSL OpenSSL::Crypto) -set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto) -set(CMAKE_REQUIRED_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) -set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}") + +if (WITH_OPENSSL_FORK) + find_package(PkgConfig) + if( ${CMAKE_PREFIX_PATH} MATCHES .*wolfssl.* ) + pkg_check_modules(WOLFSSL REQUIRED IMPORTED_TARGET wolfssl) + target_link_libraries(perf PUBLIC PkgConfig::WOLFSSL) + include_directories(BEFORE ${WOLFSSL_INCLUDE_DIRS}) + include_directories(BEFORE ${CMAKE_PREFIX_PATH}/include/wolfssl) + include_directories(BEFORE ${CMAKE_PREFIX_PATH}/include) + # + # wolfssl recommends applications to include + # wolfssl/options.h header file which is generated + # at build time during configure step. + # Instead of updating perftools applications we + # just pass missing definitions here: + # OPENSSL_EXTRA + # WOLFSSL_DTLS + # WOLFSSL_NO_OPTIONS_H + # WC_NO_HARDEN (suppresses false positive warning) + # + add_compile_definitions(WOLFSSL_NO_OPTIONS_H + WITH_OPENSSL_FORK + OPENSSL_EXTRA + WC_NO_HARDEN + WOLFSSL_DTLS) + elseif( ${CMAKE_PREFIX_PATH} MATCHES .*libressl.* ) + pkg_check_modules(LIBRESSL REQUIRED IMPORTED_TARGET openssl) + target_link_libraries(perf PUBLIC PkgConfig::LIBRESSL) + include_directories(BEFORE ${CMAKE_PREFIX_PATH}/include) + add_compile_definitions(WITH_OPENSSL_FORK) + elseif( ${CMAKE_PREFIX_PATH} MATCHES .*boringssl.* ) + find_package(OpenSSL REQUIRED ${OPENSSL_CONFIG_MODE}) + target_link_libraries(perf PUBLIC OpenSSL::SSL OpenSSL::Crypto) + include_directories(BEFORE ${CMAKE_PREFIX_PATH}/include) + add_compile_definitions(WITH_OPENSSL_FORK) + set(SKIP_HANDSHAKE 1) + set(SKIP_STOREISSUER 1) + elseif( ${CMAKE_PREFIX_PATH} MATCHES .*aws-lc.* ) + find_package(OpenSSL REQUIRED ${OPENSSL_CONFIG_MODE}) + target_link_libraries(perf PUBLIC OpenSSL::SSL OpenSSL::Crypto) + include_directories(BEFORE ${CMAKE_PREFIX_PATH}/include) + add_compile_definitions(WITH_OPENSSL_FORK) + set(SKIP_HANDSHAKE 1) + else() + message(FATAL_ERROR + "CMAKE_PREFIX_PATH does not point to wolfssl|libressl|boringssl|aws-lc") + endif() +else() + find_package(OpenSSL REQUIRED ${OPENSSL_CONFIG_MODE}) + target_link_libraries(perf PUBLIC OpenSSL::SSL OpenSSL::Crypto) + set(CMAKE_REQUIRED_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) + set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}") +endif() check_symbol_exists(OSSL_LIB_CTX_freeze "openssl/crypto.h" HAVE_OSSL_LIB_CTX_FREEZE) check_symbol_exists(SSL_set1_dnsname "openssl/ssl.h" HAVE_SSL_SET1_DNSNAME) @@ -217,6 +267,12 @@ if( OPENSSL_VERSION VERSION_GREATER_EQUAL 3 ) evp_kdf "" "" "-o evp_shared" "-o evp_isolated" "-o deprecated_shared" "-o deprecated_isolated" CACHE STRING "Modes of operation for evp_kdf") list(APPEND run_opts run_evp_kdf_operations) + if(HAVE_OSSL_LIB_CTX_FREEZE) + set(run_evp_kdf_freeze + evp_kdf "" "" "-f" + CACHE STRING "Freeze LIB_CTX for evp_kdf") + list(APPEND run_opts run_evp_kdf_freeze) + endif() add_executable(evp_rand evp_rand.c) target_link_libraries(evp_rand PRIVATE perf) @@ -261,35 +317,41 @@ list(APPEND run_tests randbytes) add_executable(handshake handshake.c) target_link_libraries(handshake PRIVATE perf) -list(APPEND run_tests handshake) -set(run_handshake_pools - handshake "" "-p" "-P" "-l" - CACHE STRING "Pool types for handshake") -list(APPEND run_opts run_handshake_pools) -set(run_handshake_ctx_sharing - handshake "" "" "-s" - CACHE STRING "Context sharing option for handshake") -list(APPEND run_opts run_handshake_ctx_sharing) -set(run_handshake_pool_size - handshake "" "" "-o 4" "-o 256" - CACHE STRING "Pool size for handshake") -list(APPEND run_opts run_handshake_pool_size) -set(run_handshake_secure_memory - handshake "" "-S 1048576" - CACHE STRING "Secure memory usage for handshake") -list(APPEND run_opts run_handshake_secure_memory) +if( NOT ${SKIP_HANDSHAKE} ) + list(APPEND run_tests handshake) + set(run_handshake_ctx_sharing + handshake "" "" "-s" + CACHE STRING "Context sharing option for handshake") + list(APPEND run_opts run_handshake_ctx_sharing) + if (NOT WITH_OPENSSL_FORK) + set(run_handshake_pools + handshake "" "-p" "-P" "-l" + CACHE STRING "Pool types for handshake") + list(APPEND run_opts run_handshake_pools) + set(run_handshake_pool_size + handshake "" "" "-o 4" "-o 256" + CACHE STRING "Pool size for handshake") + list(APPEND run_opts run_handshake_pool_size) + set(run_handshake_secure_memory + handshake "" "-S 1048576" + CACHE STRING "Secure memory usage for handshake") + list(APPEND run_opts run_handshake_secure_memory) + endif() # NOT fork +endif() # skip hadnshake add_executable(sslnew sslnew.c) target_link_libraries(sslnew PRIVATE perf) list(APPEND run_tests sslnew) -add_executable(newrawkey newrawkey.c) -target_link_libraries(newrawkey PRIVATE perf) -list(APPEND run_tests newrawkey) -set(run_newrawkey_algos - newrawkey "-a" x25519 ml-kem-512 ml-kem-768 ml-kem-1024 - CACHE STRING "Algorithms for newrawkey") -list(APPEND run_opts run_newrawkey_algos) +if (NOT WITH_OPENSSL_FORK ) + add_executable(newrawkey newrawkey.c) + target_link_libraries(newrawkey PRIVATE perf) + list(APPEND run_tests newrawkey) + set(run_newrawkey_algos + newrawkey "-a" x25519 ml-kem-512 ml-kem-768 ml-kem-1024 + CACHE STRING "Algorithms for newrawkey") + list(APPEND run_opts run_newrawkey_algos) +endif() add_executable(rsasign rsasign.c) target_link_libraries(rsasign PRIVATE perf) @@ -297,78 +359,88 @@ list(APPEND run_tests rsasign) add_executable(x509storeissuer x509storeissuer.c) target_link_libraries(x509storeissuer PRIVATE perf) -list(APPEND run_tests x509storeissuer) +if( NOT ${SKIP_STOREISSUER} ) + list(APPEND run_tests x509storeissuer) +endif() -add_executable(rwlocks rwlocks.c) -target_link_libraries(rwlocks PRIVATE perf) -list(APPEND run_tests rwlocks) +if( NOT WITH_OPENSSL_FORK ) + add_executable(rwlocks rwlocks.c) + target_link_libraries(rwlocks PRIVATE perf) + list(APPEND run_tests rwlocks) +endif() -add_executable(pkeyread pkeyread.c) -if(WIN32) - target_link_libraries(pkeyread PRIVATE perf) -else() - target_link_libraries(pkeyread PUBLIC m PRIVATE perf) +if( NOT WITH_OPENSSL_FORK ) + add_executable(pkeyread pkeyread.c) + if(WIN32) + target_link_libraries(pkeyread PRIVATE perf) + else() + target_link_libraries(pkeyread PUBLIC m PRIVATE perf) + endif() + list(APPEND run_tests pkeyread) + set(run_pkeyread_keys + pkeyread "-k" dh dhx dsa ec rsa x25519 all + CACHE STRING "Key types for pkeyread") + list(APPEND run_opts run_pkeyread_keys) + set(run_pkeyread_fmts + pkeyread "-f" pem der all + CACHE STRING "Key formats for pkeyread") + list(APPEND run_opts run_pkeyread_fmts) endif() -list(APPEND run_tests pkeyread) -set(run_pkeyread_keys - pkeyread "-k" dh dhx dsa ec rsa x25519 all - CACHE STRING "Key types for pkeyread") -list(APPEND run_opts run_pkeyread_keys) -set(run_pkeyread_fmts - pkeyread "-f" pem der all - CACHE STRING "Key formats for pkeyread") -list(APPEND run_opts run_pkeyread_fmts) add_executable(evp_setpeer evp_setpeer.c) target_link_libraries(evp_setpeer PRIVATE perf) list(APPEND run_tests evp_setpeer) -set(run_evp_setpeer_keys - evp_setpeer "-k" dh ec256 ec521 x25519 all - CACHE STRING "Key types for evp_setpeer") +if ( WITH_OPENSSL_FORK ) + set(run_evp_setpeer_keys + evp_setpeer "-k" ec256 ec521 + CACHE STRING "Key types for evp_setpeer") +else() + set(run_evp_setpeer_keys + evp_setpeer "-k" dh ec256 ec521 x25519 all + CACHE STRING "Key types for evp_setpeer") +endif() list(APPEND run_opts run_evp_setpeer_keys) add_executable(writeread writeread.c) target_link_libraries(writeread PRIVATE perf) list(APPEND run_tests writeread) -set(run_writeread_ctx_sharing - writeread "" "" "-s" - CACHE STRING "Context sharing for writeread") -list(APPEND run_opts run_writeread_ctx_sharing) -set(run_writeread_dtls - writeread "" "" "-d" - CACHE STRING "DTLS mode for writeread") -list(APPEND run_opts run_writeread_dtls) +if (NOT WITH_OPENSSL_FORK) + set(run_writeread_ctx_sharing + writeread "" "" "-s" + CACHE STRING "Context sharing for writeread") + list(APPEND run_opts run_writeread_ctx_sharing) + set(run_writeread_dtls + writeread "" "" "-d" + CACHE STRING "DTLS mode for writeread") + list(APPEND run_opts run_writeread_dtls) +endif() set(run_writeread_buffers writeread "" "" "-b 256" "-b 4096" CACHE STRING "Buffer size for writeread") list(APPEND run_opts run_writeread_buffers) -add_executable(evp_hash evp_hash.c) -target_link_libraries(evp_hash PRIVATE perf) -list(APPEND run_tests evp_hash) -if( HAVE_OSSL_LIB_CTX_FREEZE ) - set(run_evp_kdf_freeze - evp_kdf "" "" "-f" - CACHE STRING "Freeze LIB_CTX for evp_kdf") - list(APPEND run_opts run_evp_kdf_freeze) -endif() -set(run_evp_hash_operations - evp_hash "" "" "-o deprecated" "-o evp_isolated" "-o evp_shared" - CACHE STRING "Modes of operation for evp_hash") -list(APPEND run_opts run_evp_hash_operations) -set(run_evp_hash_update_times - evp_hash "" "" "-u 1" "-u 5" - CACHE STRING "Digest update times for evp_hash") -list(APPEND run_opts run_evp_hash_update_times) -set(run_evp_hash_algorithms - evp_hash "" "" "-a SHA1" "-a SHA224" "-a SHA256" "-a SHA384" "-a SHA512" - CACHE STRING "Digest hash algorithms for evp_hash") -list(APPEND run_opts run_evp_hash_algorithms) -if(HAVE_OSSL_LIB_CTX_FREEZE) - set(run_evp_hash_freeze - evp_hash "" "" "-f" - CACHE STRING "Freeze LIB_CTX for evp_hash") - list(APPEND run_opts run_evp_hash_freeze) +if( NOT WITH_OPENSSL_FORK ) + add_executable(evp_hash evp_hash.c) + target_link_libraries(evp_hash PRIVATE perf) + list(APPEND run_tests evp_hash) + set(run_evp_hash_operations + evp_hash "" "" "-o deprecated" "-o evp_isolated" "-o evp_shared" + CACHE STRING "Modes of operation for evp_hash") + list(APPEND run_opts run_evp_hash_operations) + set(run_evp_hash_update_times + evp_hash "" "" "-u 1" "-u 5" + CACHE STRING "Digest update times for evp_hash") + list(APPEND run_opts run_evp_hash_update_times) + set(run_evp_hash_algorithms + evp_hash "" "" "-a SHA1" "-a SHA224" "-a SHA256" "-a SHA384" "-a SHA512" + CACHE STRING "Digest hash algorithms for evp_hash") + list(APPEND run_opts run_evp_hash_algorithms) + if(HAVE_OSSL_LIB_CTX_FREEZE) + set(run_evp_hash_freeze + evp_hash "" "" "-f" + CACHE STRING "Freeze LIB_CTX for evp_hash") + list(APPEND run_opts run_evp_hash_freeze) + endif() endif() set(run_add_version_dep ON @@ -378,15 +450,24 @@ set(run_add_version_dep ON # Used across multiple tests set(run_certdir_tests handshake writeread x509storeissuer CACHE STRING "List of tests that require certdir parameter") -file(TO_NATIVE_PATH "${OPENSSL_ROOT_DIR}/test/certs/" run_certdir_def_path) +if ( WITH_OPENSSL_FORK ) + file(TO_NATIVE_PATH "${OPENSSL_SOURCE}/test/certs/" run_certdir_def_path) +else() + file(TO_NATIVE_PATH "${OPENSSL_ROOT_DIR}/test/certs/" run_certdir_def_path) +endif() set(run_certdir "${run_certdir_def_path}" CACHE PATH "Path to certificates directory for tests that need it") # Common options set(run_terse "" "-t" CACHE STRING "List of terse output options") -set(run_threads 1 4 - CACHE STRING "List of thread counts") +if( WITH_OPENSSL_FORK ) + set(run_threads 1 + CACHE STRING "List of thread counts") +else() + set(run_threads 1 4 + CACHE STRING "List of thread counts") +endif() add_custom_target(run COMMENT "Run perf tests" diff --git a/source/evp_hash.c b/source/evp_hash.c index f3305f46..7c073161 100644 --- a/source/evp_hash.c +++ b/source/evp_hash.c @@ -30,6 +30,8 @@ #include #include "perflib/perflib.h" +#include + #define RUN_TIME 5 #define DATA_SIZE 1500 @@ -355,7 +357,7 @@ int main(int argc, char *argv[]) if (!RAND_bytes((unsigned char *)data, sizeof(data))) goto out; - counts = OPENSSL_zalloc(sizeof(size_t) * threadcount); + counts = calloc(1, sizeof(size_t) * threadcount); if (counts == NULL) { fprintf(stderr, "Failed to create counts array\n"); goto out; diff --git a/source/evp_mac.c b/source/evp_mac.c index 03c6e7df..1838b075 100644 --- a/source/evp_mac.c +++ b/source/evp_mac.c @@ -18,6 +18,7 @@ #include #ifndef _WIN32 # include +# include #else # include "perflib/getopt.h" #endif /* _WIN32 */ diff --git a/source/evp_setpeer.c b/source/evp_setpeer.c index f27a04b9..f0292e9c 100644 --- a/source/evp_setpeer.c +++ b/source/evp_setpeer.c @@ -19,6 +19,7 @@ # include "perflib/getopt.h" #endif /* _WIN32 */ #include +#include #include "perflib/perflib.h" /* run 'make regen_key_samples' if header file is missing */ diff --git a/source/handshake.c b/source/handshake.c index 87685953..c00410df 100644 --- a/source/handshake.c +++ b/source/handshake.c @@ -402,6 +402,10 @@ int main(int argc, char * const argv[]) break; #endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */ case 'S': { +#ifdef WITH_OPENSSL_FORK + fprintf(stderr, "Secure malloc is not support for OpenSSL forks\n");; + return EXIT_FAILURE; +#else char *end = NULL; int sec_mem_size; @@ -420,6 +424,7 @@ int main(int argc, char * const argv[]) fprintf(stderr, "Secure heap not initialized\n"); return EXIT_FAILURE; } +#endif break; } case 'V': diff --git a/source/perflib/perfhelper.c b/source/perflib/perfhelper.c index f0ce2ac9..a2eb75cd 100644 --- a/source/perflib/perfhelper.c +++ b/source/perflib/perfhelper.c @@ -20,14 +20,23 @@ char *perflib_mk_file_path(const char *dir, const char *file) const char *sep = "/"; size_t dirlen = dir != NULL ? strlen(dir) : 0; size_t len = dirlen + strlen(sep) + strlen(file) + 1; - char *full_file = OPENSSL_zalloc(len); + char *full_file = calloc(1, len); if (full_file != NULL) { if (dir != NULL && dirlen > 0) { +#ifdef WITH_OPENSSL_FORK + strlcpy(full_file, dir, len); + strlcat(full_file, sep, len); +#else OPENSSL_strlcpy(full_file, dir, len); OPENSSL_strlcat(full_file, sep, len); +#endif } +#ifdef WITH_OPENSSL_FORK + strlcat(full_file, file, len); +#else OPENSSL_strlcat(full_file, file, len); +#endif } return full_file; diff --git a/source/perflib/perfsslhelper.c b/source/perflib/perfsslhelper.c index cf32394f..25131df7 100644 --- a/source/perflib/perfsslhelper.c +++ b/source/perflib/perfsslhelper.c @@ -247,7 +247,7 @@ int perflib_create_ssl_connection(SSL *serverssl, SSL *clientssl, int want) { int i; unsigned char buf; - size_t readbytes; + int readbytes; if (!perflib_create_bare_ssl_connection(serverssl, clientssl, want)) return 0; @@ -258,7 +258,8 @@ int perflib_create_ssl_connection(SSL *serverssl, SSL *clientssl, int want) * appropriate. We do this twice because there are 2 NewSessionTickets. */ for (i = 0; i < 2; i++) { - if (SSL_read_ex(clientssl, &buf, sizeof(buf), &readbytes) > 0) { + readbytes = SSL_read(clientssl, &buf, sizeof(buf)); + if (readbytes >= 0) { if (readbytes != 0) { printf("Unexpected data reading ticket\n"); return 0; diff --git a/source/perflib/safe_math.h b/source/perflib/safe_math.h index 10ecf266..3e79a00e 100644 --- a/source/perflib/safe_math.h +++ b/source/perflib/safe_math.h @@ -12,7 +12,13 @@ # pragma once # include +#ifndef WITH_OPENSSL_FORK # include /* For 'ossl_inline' */ +#else + +#define ossl_inline inline +#define ossl_unused +#endif # ifndef OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING # ifdef __has_builtin diff --git a/source/perflib/time.h b/source/perflib/time.h index 94584b2e..391b53d7 100644 --- a/source/perflib/time.h +++ b/source/perflib/time.h @@ -11,7 +11,8 @@ # define OSSL_PERFLIB_TIME_H # pragma once -# include /* uint64_t */ +#include + # ifndef _WIN32 # include "sys/time.h" # else @@ -50,6 +51,18 @@ typedef struct { #define ossl_us2time(us) ossl_ticks2time((us) * OSSL_TIME_US) #define ossl_time2us(t) (ossl_time2ticks(t) / OSSL_TIME_US) +#ifndef ossl_unused +#if defined(__GNUC__) +#define ossl_unused __attribute__((unused)) +#else +#define ossl_unused +#endif +#endif + +#ifndef ossl_inline +#define ossl_inline inline +#endif + /* Convert a tick count into a time */ static ossl_unused ossl_inline OSSL_TIME ossl_ticks2time(uint64_t ticks) diff --git a/source/writeread.c b/source/writeread.c index 60550664..6a845a39 100644 --- a/source/writeread.c +++ b/source/writeread.c @@ -73,20 +73,22 @@ static void do_writeread(size_t num) } do { - size_t written = 0; - if (SSL_write_ex(clientssl, cbuf, buf_size, &written) <= 0) { + int written = 0; + written = SSL_write(clientssl, cbuf, buf_size); + if (written <= 0) { fprintf(stderr, "Failed to write data\n"); err = 1; return; } - size_t readbytes; - if (SSL_read_ex(serverssl, sbuf, buf_size, &readbytes) <= 0) { + int readbytes; + readbytes = SSL_read(serverssl, sbuf, buf_size); + if (readbytes <= 0) { fprintf(stderr, "Failed to read data\n"); err = 1; return; } if (readbytes != written) { - fprintf(stderr, "Failed to read %ld bytes, got %ld\n", written, readbytes); + fprintf(stderr, "Failed to read %d bytes, got %d\n", written, readbytes); err = 1; return; } @@ -173,7 +175,7 @@ int main(int argc, char * const argv[]) goto err; } - counts = OPENSSL_zalloc(sizeof(size_t) * threadcount); + counts = calloc(1, sizeof(size_t) * threadcount); if (counts == NULL) { fprintf(stderr, "Failed to create counts array\n"); goto err; @@ -212,9 +214,9 @@ int main(int argc, char * const argv[]) ret = EXIT_SUCCESS; err: - OPENSSL_free(cert); - OPENSSL_free(privkey); - OPENSSL_free(counts); + free(cert); + free(privkey); + free(counts); if (share_ctx == 1) { SSL_CTX_free(sctx); SSL_CTX_free(cctx);