/* * Copyright 2025 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 */ #include #include #include #include #include "helpers/ssltestlib.h" #include "testutil.h" /** * @brief Global static variables for certificate and key handling. * * These variables store the paths and context used for managing * certificates and private keys in the application. * * - certsdir: Directory containing trusted certificates. * - cert: Path to the certificate file in use. * - privkey: Path to the private key file. * - mcount: Number of mallocs counted * - rcount: Number of reallocs counted * - fcount: Number of frees counted * - scount: Number of mallocs counted prior to workload */ static char *cert = NULL; static char *privkey = NULL; static int mcount, rcount, fcount, scount; /** * @brief Performs an SSL/TLS handshake between a test client and server. * * This function sets up SSL/TLS contexts and objects for both client and * server, then initiates a handshake to verify successful connection * establishment. It is intended for use in testing scenarios to validate * handshake behavior using specified certificates and keys. * * @return 1 on successful handshake, 0 on failure. * * @note The function uses @c TEST_true() macros to validate intermediate * steps. All SSL objects and contexts are freed before returning. */ static int do_handshake(OSSL_LIB_CTX *libctx) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; int testresult = 0; if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(), TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) return 0; /* Now do a handshake */ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) || !TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) goto end; testresult = 1; end: SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx); SSL_CTX_free(cctx); return testresult; } /** * @brief run our workload to count the number of allocations we make. * * Creates a new OpenSSL library context and performs a test SSL/TLS * handshake. The number of malloc operations is recorded and printed for * diagnostic purposes. * * @return 1 if the handshake succeeds, 0 otherwise. */ static int test_record_alloc_counts(void) { int ret; OSSL_LIB_CTX *libctx; libctx = OSSL_LIB_CTX_new(); if (!TEST_ptr(libctx)) return 0; ret = do_handshake(libctx); OSSL_LIB_CTX_free(libctx); libctx = NULL; return ret; } /** * @brief run our workload to count the number of allocations we make. * * Creates a new OpenSSL library context and performs a test SSL/TLS * handshake. * * Note this is exactly the same as test_record_alloc_counts with 1 difference * The test always returns 1. We do this because with allocation failures * in effect, we can't expect things to work, so we always return success * so that the test keeps running. */ static int test_alloc_failures(void) { OSSL_LIB_CTX *libctx; libctx = OSSL_LIB_CTX_new(); if (!TEST_ptr(libctx)) return 1; do_handshake(libctx); OSSL_LIB_CTX_free(libctx); libctx = NULL; return 1; } static int test_report_alloc_counts(void) { CRYPTO_get_alloc_counts(&mcount, &rcount, &fcount); /* * Report our memory allocations from the count run * NOTE: We report a number of allocations to skip here * (the scount value). These are the allocations that took * place while the test harness itself was getting setup * (i.e. calling OPENSSL_init_crypto/etc). We can't fail * those allocations as they will cause the test to fail before * we have even run the workload. So report them so we can * allow them to function before we start doing any real testing */ TEST_info("skip: %d count %d\n", scount, mcount - scount); return 1; } int setup_tests(void) { char *opmode = NULL; char *certsdir = NULL; if (!TEST_ptr(opmode = test_get_argument(0))) goto err; if (!TEST_ptr(certsdir = test_get_argument(1))) goto err; cert = test_mk_file_path(certsdir, "servercert.pem"); if (cert == NULL) goto err; privkey = test_mk_file_path(certsdir, "serverkey.pem"); if (privkey == NULL) goto err; if (strcmp(opmode, "count") == 0) { CRYPTO_get_alloc_counts(&scount, &rcount, &fcount); ADD_TEST(test_record_alloc_counts); ADD_TEST(test_report_alloc_counts); } else { ADD_TEST(test_alloc_failures); } return 1; err: OPENSSL_free(cert); OPENSSL_free(privkey); return 0; } void cleanup_tests(void) { OPENSSL_free(cert); OPENSSL_free(privkey); }