From c1d5f5c2980a92a41252b7efa37f748a87d426c8 Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Wed, 28 Jan 2026 15:28:43 +0100 Subject: [PATCH] Let perftools to also bench OpenSSL forks. This change adjusts existing perftools so they cne be built by 3rd party SSL libraries (a.k.a. OpenSSL forks). Currently those tools can be used to bench OpenSSL forks: randbytes, rsasign, handshake, sslnew, x509storeissuer. evp_setpeer, writeread The change also adds bench_config_forks.sh which installs forks and builds perftools. And bench_run_forks.sh which runs tests and plots results. Fixes https://github.com/openssl/project/issues/1845 --- bench-scripts/README.md | 15 ++ bench-scripts/bench_config_forks.sh | 88 ++++++++ bench-scripts/bench_run_forks.sh | 319 ++++++++++++++++++++++++++++ bench-scripts/common_util.sh | 23 +- source/CMakeLists.txt | 255 ++++++++++++++-------- source/evp_hash.c | 4 +- source/evp_mac.c | 1 + source/evp_setpeer.c | 1 + source/handshake.c | 5 + source/perflib/perfhelper.c | 11 +- source/perflib/perfsslhelper.c | 5 +- source/perflib/safe_math.h | 6 + source/perflib/time.h | 15 +- source/writeread.c | 20 +- 14 files changed, 666 insertions(+), 102 deletions(-) create mode 100755 bench-scripts/bench_config_forks.sh create mode 100755 bench-scripts/bench_run_forks.sh 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);