Add ocsp responder test to testsuite.c and tested on windows

This commit is contained in:
Juliusz Sosinowicz
2026-02-26 15:24:59 +01:00
parent a795b19db2
commit 9a9eb2bf1d
13 changed files with 244 additions and 30 deletions
+5
View File
@@ -40,6 +40,11 @@
#define HAVE_CRL
#define HAVE_CRL_MONITOR
#define HAVE_OCSP
#define HAVE_OCSP_RESPONDER
#define WOLFSSL_CERT_GEN
#define HAVE_CERTIFICATE_STATUS_REQUEST
#if defined(WOLFSSL_LIB)
/* The lib */
#define OPENSSL_EXTRA
+44 -13
View File
@@ -53,8 +53,10 @@
#include <string.h>
/* Define mygetopt variables (used by mygetopt_long in test.h) */
#ifndef NO_MAIN_DRIVER
int myoptind = 0;
char* myoptarg = NULL;
#endif
#ifdef _WIN32
#include <winsock2.h>
@@ -84,15 +86,6 @@ char* myoptarg = NULL;
#define MAX_PATH_LEN 256
#define MAX_CERTS 16
/* Simple logging macro */
#define LOG_ERROR(...) \
do { \
if (got_signal) \
fprintf(stderr, "Shutdown requested, exiting loop\n"); \
else \
fprintf(stderr, __VA_ARGS__); \
} while (0)
#define LOG_MSG(...) \
do { \
@@ -109,6 +102,21 @@ static void sig_handler(int sig)
(void)sig;
got_signal = 1;
}
/* Simple logging macro */
#define LOG_ERROR(...) \
do { \
if (got_signal) \
fprintf(stderr, "Shutdown requested, exiting loop\n"); \
else \
fprintf(stderr, __VA_ARGS__); \
} while (0)
#else
/* Simple logging macro */
#define LOG_ERROR(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
} while (0)
#endif
/* Index file entry structure */
@@ -737,6 +745,8 @@ THREAD_RETURN WOLFSSL_THREAD ocsp_responder_test(void* args)
}
}
myoptind = 0; /* reset for test cases */
/* Validate required options */
if (opts.certFile == NULL) {
LOG_ERROR("Error: CA certificate required (-c)\n");
@@ -855,9 +865,32 @@ THREAD_RETURN WOLFSSL_THREAD ocsp_responder_test(void* args)
}
}
#ifdef USE_WINDOWS_API
if (opts.port == 0) {
/* Generate random port for testing */
opts.port = GetRandomPort();
}
#endif /* USE_WINDOWS_API */
/* Create and listen on server socket */
tcp_listen(&sockfd, &opts.port, 1, 0, 0);
#ifndef SINGLE_THREADED
/* Signal readiness via tcp_ready if provided (for in-process testing) */
if (myargs->signal != NULL) {
tcp_ready* ready = myargs->signal;
#ifdef WOLFSSL_COND
THREAD_CHECK_RET(wolfSSL_CondStart(&ready->cond));
#endif
ready->ready = 1;
ready->port = opts.port;
#ifdef WOLFSSL_COND
THREAD_CHECK_RET(wolfSSL_CondSignal(&ready->cond));
THREAD_CHECK_RET(wolfSSL_CondEnd(&ready->cond));
#endif
}
#endif /* !SINGLE_THREADED */
/* Write ready file if requested */
if (opts.readyFile != NULL) {
XFILE rf = XFOPEN(opts.readyFile, "w");
@@ -1007,10 +1040,6 @@ cleanup:
if (caKeyDer)
XFREE(caKeyDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#ifdef _WIN32
WSACleanup();
#endif
myargs->return_code = ret;
#ifndef WOLFSSL_THREAD_VOID_RETURN
return (THREAD_RETURN)0;
@@ -1025,6 +1054,8 @@ int main(int argc, char** argv)
func_args args;
int ret;
StartTCP();
#ifdef HAVE_WNR
if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) {
err_sys("Whitewood netRandom global config failed");
+3 -3
View File
@@ -2642,7 +2642,7 @@ int wolfSSL_X509_CRL_sign(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* pkey,
CRL_Entry* entry;
byte* issuerDer = NULL;
int issuerSz = 0;
int sigType;
int sigType = 0;
int tbsSz = 0;
int totalSz = 0;
byte* buf = NULL;
@@ -2882,10 +2882,10 @@ int wolfSSL_X509_CRL_sign(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* pkey,
*/
{
word32 idx = 0;
int len;
int len = 0;
word32 tbsStart = 0;
word32 tbsLen = 0;
int sigLen;
int sigLen = 0;
/* Parse outer SEQUENCE */
if (GetSequence(buf, &idx, &len, (word32)totalSz) < 0) {
+2 -2
View File
@@ -6015,11 +6015,11 @@ int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
break;
#endif /* WOLFSSL_KEY_GEN && !NO_RSA */
#if !defined(NO_DSA) && !defined(HAVE_SELFTEST) && \
(defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN))
defined(WOLFSSL_KEY_GEN)
case WC_EVP_PKEY_DSA:
ret = wolfSSL_PEM_write_bio_DSA_PUBKEY(bio, key->dsa);
break;
#endif /* !NO_DSA && !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) */
#endif /* !NO_DSA && !HAVE_SELFTEST && defined(WOLFSSL_KEY_GEN) */
#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \
defined(WOLFSSL_KEY_GEN)
case WC_EVP_PKEY_EC:
+3 -3
View File
@@ -2993,10 +2993,10 @@ int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s)
don't allow chain ones to be added w/o isCA extension */
int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
{
int ret;
int ret = 0;
Signer* signer = NULL;
word32 row;
byte* subjectHash;
word32 row = 0;
byte* subjectHash = NULL;
WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
DerBuffer* der = *pDer;
+2 -2
View File
@@ -8732,7 +8732,7 @@ static int WriteCSRToBuffer(WOLFSSL* ssl, DerBuffer** certExts,
if (tmpSz > (OPAQUE8_LEN + OPAQUE24_LEN) &&
certExts[extIdx] == NULL) {
/* csr extension is not zero */
extSz[extIdx] = tmpSz;
extSz[extIdx] = (word16)tmpSz;
ret = AllocDer(&certExts[extIdx], extSz[extIdx] + ex_offset,
CERT_TYPE, ssl->heap);
@@ -8972,7 +8972,7 @@ static int SendTls13Certificate(WOLFSSL* ssl)
return ret;
ret = WriteCSRToBuffer(ssl, &ssl->buffers.certExts[0], &extSz[0],
1 /* +1 for leaf */ + ssl->buffers.certChainCnt);
1 /* +1 for leaf */ + (word16)ssl->buffers.certChainCnt);
if (ret < 0)
return ret;
totalextSz += ret;
+1 -1
View File
@@ -11822,7 +11822,7 @@ static int CertFromX509(Cert* cert, WOLFSSL_X509* x509)
cert->isCA = wolfSSL_X509_get_isCA(x509);
cert->basicConstCrit = x509->basicConstCrit;
cert->basicConstSet = x509->basicConstSet;
cert->pathLen = x509->pathLength;
cert->pathLen = (byte)x509->pathLength;
cert->pathLenSet = x509->pathLengthSet;
#ifdef WOLFSSL_CERT_EXT
+1
View File
@@ -12,6 +12,7 @@ testsuite_testsuite_test_SOURCES = \
examples/echoclient/echoclient.c \
examples/echoserver/echoserver.c \
examples/server/server.c \
examples/ocsp_responder/ocsp_responder.c \
testsuite/testsuite.c
testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUDE)
testsuite_testsuite_test_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB)
+174
View File
@@ -51,6 +51,10 @@
#include <examples/echoserver/echoserver.h>
#include <examples/server/server.h>
#include <examples/client/client.h>
#if defined(HAVE_OCSP) && defined(HAVE_OCSP_RESPONDER) && \
!defined(NO_FILESYSTEM)
#include <examples/ocsp_responder/ocsp_responder.h>
#endif
#include <testsuite/utils.h>
/* include source file to not change all the testsuite build systems */
@@ -73,6 +77,12 @@ static int test_tls(func_args* server_args);
defined(HAVE_CRL) && defined(HAVE_CRL_MONITOR)
static int test_crl_monitor(void);
#endif
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
!defined(NO_TLS) && !defined(NETOS) && defined(HAVE_OCSP) && \
defined(HAVE_OCSP_RESPONDER) && !defined(NO_FILESYSTEM) && \
!defined(NO_RSA) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
static int test_ocsp_responder(void);
#endif
static void show_ciphers(void);
static void cleanup_output(void);
static int validate_cleanup_output(void);
@@ -244,6 +254,17 @@ int testsuite_test(int argc, char** argv)
}
#endif
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
!defined(NO_TLS) && !defined(NETOS) && defined(HAVE_OCSP) && \
defined(HAVE_OCSP_RESPONDER) && !defined(NO_FILESYSTEM) && \
!defined(NO_RSA) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
ret = test_ocsp_responder();
if (ret != 0) {
cleanup_output();
return ret;
}
#endif
#endif /* !NETOS */
show_ciphers();
@@ -424,6 +445,159 @@ cleanup:
}
#endif
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
!defined(NO_TLS) && !defined(NETOS) && defined(HAVE_OCSP) && \
defined(HAVE_OCSP_RESPONDER) && !defined(NO_FILESYSTEM) && \
!defined(NO_RSA) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
/* Run a single OCSP-responder-backed stapling test.
* serverCert - path to the TLS server certificate (chain file)
* serverKey - path to the TLS server private key
* expectPass - non-zero if the client handshake should succeed
* Returns 0 on success, non-zero on failure. */
static int run_ocsp_responder_test_case(const char* serverCert,
const char* serverKey,
int expectPass)
{
func_args respArgs;
func_args svrArgs;
func_args cliArgs;
THREAD_TYPE respThread;
THREAD_TYPE svrThread;
tcp_ready respReady;
tcp_ready svrReady;
/* Buffers for runtime-built argv entries */
char ocspUrl[64];
char svrPortStr[8];
/* argv arrays (non-const so they can be assigned to char**) */
char* respArgv[12];
char* svrArgv[15];
char* cliArgv[12];
int ret = -1;
/* OCSP responder argv */
respArgv[0] = (char*)"ocsp_responder";
respArgv[1] = (char*)"-p"; respArgv[2] = (char*)"0";
respArgv[3] = (char*)"-n"; respArgv[4] = (char*)"1";
respArgv[5] = (char*)"-c";
respArgv[6] = (char*)"certs/ocsp/intermediate1-ca-cert.pem";
respArgv[7] = (char*)"-k";
respArgv[8] = (char*)"certs/ocsp/intermediate1-ca-key.pem";
respArgv[9] = (char*)"-i";
respArgv[10] = (char*)"certs/ocsp/index-intermediate1-ca-issued-certs.txt";
respArgv[11] = NULL;
XMEMSET(&respArgs, 0, sizeof(respArgs));
InitTcpReady(&respReady);
respArgs.signal = &respReady;
respArgs.argc = 11;
respArgs.argv = respArgv;
start_thread(ocsp_responder_test, &respArgs, &respThread);
wait_tcp_ready(&respArgs);
/* Build OCSP URL override pointing at the dynamic responder port */
(void)XSNPRINTF(ocspUrl, sizeof(ocspUrl),
"http://127.0.0.1:%d", (int)respReady.port);
/* TLS server argv */
svrArgv[0] = (char*)"testsuite";
svrArgv[1] = (char*)"-c"; svrArgv[2] = (char*)serverCert;
svrArgv[3] = (char*)"-k"; svrArgv[4] = (char*)serverKey;
svrArgv[5] = (char*)"-d"; /* no client cert required */
svrArgv[6] = (char*)"-x"; /* runWithErrors: don't exit on SSL_accept fail */
svrArgv[7] = (char*)"-C"; svrArgv[8] = (char*)"1"; /* one connection */
svrArgv[9] = (char*)"-O"; svrArgv[10] = ocspUrl; /* OCSP override */
svrArgv[11] = (char*)"--quieter";
svrArgv[12] = (char*)"-p"; svrArgv[13] = (char*)"0";
svrArgv[14] = NULL;
XMEMSET(&svrArgs, 0, sizeof(svrArgs));
InitTcpReady(&svrReady);
svrArgs.signal = &svrReady;
svrArgs.argc = 14;
svrArgs.argv = svrArgv;
start_thread(server_test, &svrArgs, &svrThread);
wait_tcp_ready(&svrArgs);
/* Build server port string now that it is bound */
(void)XSNPRINTF(svrPortStr, sizeof(svrPortStr), "%d",
(int)svrArgs.signal->port);
/* TLS client argv */
cliArgv[0] = (char*)"testsuite";
cliArgv[1] = (char*)"-A";
cliArgv[2] = (char*)"certs/ocsp/root-ca-cert.pem";
cliArgv[3] = (char*)"-C"; /* disable CRL */
cliArgv[4] = (char*)"-W"; cliArgv[5] = (char*)"1"; /* OCSP stapling */
cliArgv[6] = (char*)"-H"; cliArgv[7] = (char*)"exitWithRet";
cliArgv[8] = (char*)"--quieter";
cliArgv[9] = (char*)"-p"; cliArgv[10] = svrPortStr;
cliArgv[11] = NULL;
XMEMSET(&cliArgs, 0, sizeof(cliArgs));
cliArgs.signal = &svrReady;
cliArgs.argc = 11;
cliArgs.argv = cliArgv;
client_test(&cliArgs);
join_thread(svrThread);
join_thread(respThread);
FreeTcpReady(&svrReady);
FreeTcpReady(&respReady);
if (expectPass) {
if (cliArgs.return_code != 0) {
fprintf(stderr, "OCSP stapling test: expected success, "
"client returned %d\n", cliArgs.return_code);
}
else {
ret = 0;
}
}
else {
if (cliArgs.return_code == 0) {
fprintf(stderr, "OCSP stapling test: expected failure "
"(revoked cert), but client returned 0\n");
}
else {
ret = 0;
}
}
return ret;
}
/* Test the OCSP responder example together with TLS OCSP stapling.
*
* Case 1: server cert is valid -> client handshake must succeed.
* Case 2: server cert is revoked -> client handshake must fail.
*/
static int test_ocsp_responder(void)
{
int ret;
printf("\nRunning OCSP responder test\n");
/* Test 1: valid certificate - connection should succeed */
ret = run_ocsp_responder_test_case("certs/ocsp/server1-cert.pem",
"certs/ocsp/server1-key.pem", 1);
if (ret != 0) {
fprintf(stderr, "OCSP responder test (good cert) failed\n");
return ret;
}
/* Test 2: revoked certificate - connection should be rejected */
ret = run_ocsp_responder_test_case("certs/ocsp/server2-cert.pem",
"certs/ocsp/server2-key.pem", 0);
if (ret != 0) {
fprintf(stderr, "OCSP responder test (revoked cert) failed\n");
return ret;
}
return 0;
}
#endif /* HAVE_OCSP && HAVE_OCSP_RESPONDER */
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
!defined(NO_TLS) && \
(!defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC))
+3
View File
@@ -189,6 +189,9 @@
<File
RelativePath="..\examples\server\server.c"
>
<File
RelativePath="..\examples\ocsp_responder\ocsp_responder.c"
>
</File>
<File
RelativePath="..\wolfcrypt\test\test.c"
+1
View File
@@ -471,6 +471,7 @@
<ClCompile Include="..\examples\echoclient\echoclient.c" />
<ClCompile Include="..\examples\echoserver\echoserver.c" />
<ClCompile Include="..\examples\server\server.c" />
<ClCompile Include="..\examples\ocsp_responder\ocsp_responder.c" />
<ClCompile Include="..\wolfcrypt\test\test.c" />
<ClCompile Include="testsuite.c" />
</ItemGroup>
+4 -5
View File
@@ -39153,7 +39153,7 @@ WC_MAYBE_UNUSED static int EncodeCertID(OcspEntry* entry, byte* out,
DECL_ASNSETDATA(dataASN, certidasn_Length);
int ret = 0;
int sz = 0;
word32 digestSz;
word32 digestSz = 0;
if (entry == NULL || entry->status == NULL ||
entry->status->serialSz <= 0 || outSz == NULL) {
@@ -40204,7 +40204,8 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
#else
DECL_ASNGETDATA(dataASN, ocspRespDataASN_Length);
int ret = 0;
byte version;
/* Default, not present, is v1 = 0. */
byte version = 0;
word32 dateSz = 0;
word32 responderByKeySz = OCSP_RESPONDER_ID_KEY_SZ;
word32 idx = *ioIndex;
@@ -40216,8 +40217,6 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
if (ret == 0) {
resp->response = source + idx;
/* Default, not present, is v1 = 0. */
version = 0;
/* Max size of date supported. */
dateSz = MAX_DATE_SIZE;
@@ -40995,7 +40994,7 @@ int OcspResponseEncode(OcspResponse* resp, byte* out, word32* outSz,
if (ret == 0) {
SetASN_Int8Bit(&dataASN[OCSPRESPONSEASN_IDX_STATUS],
resp->responseStatus);
(byte)resp->responseStatus);
}
if (ret == 0 && resp->responseStatus == OCSP_SUCCESSFUL) {
SetASN_OID(&dataASN[OCSPRESPONSEASN_IDX_BYTES_TYPE], OCSP_BASIC_OID,
+1 -1
View File
@@ -4161,7 +4161,7 @@ int wc_RsaPSS_CheckPadding_ex2(const byte* in, word32 inSz, const byte* sig,
/* Sig = Salt | Exp Hash */
if (ret == 0) {
word32 totalSz;
word32 totalSz = 0;
if ((WC_SAFE_SUM_WORD32(inSz, (word32)saltLen, totalSz) == 0) ||
(sigSz != totalSz))
{