diff --git a/IDE/WIN/user_settings.h b/IDE/WIN/user_settings.h index a1011abf8c..dfd137c0b8 100644 --- a/IDE/WIN/user_settings.h +++ b/IDE/WIN/user_settings.h @@ -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 diff --git a/examples/ocsp_responder/ocsp_responder.c b/examples/ocsp_responder/ocsp_responder.c index f6d0664fb3..5d019810e1 100644 --- a/examples/ocsp_responder/ocsp_responder.c +++ b/examples/ocsp_responder/ocsp_responder.c @@ -53,8 +53,10 @@ #include /* Define mygetopt variables (used by mygetopt_long in test.h) */ +#ifndef NO_MAIN_DRIVER int myoptind = 0; char* myoptarg = NULL; +#endif #ifdef _WIN32 #include @@ -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"); diff --git a/src/crl.c b/src/crl.c index b382ef7baf..0805b32f8d 100644 --- a/src/crl.c +++ b/src/crl.c @@ -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) { diff --git a/src/pk.c b/src/pk.c index 14d25e14d9..1aaf40d065 100644 --- a/src/pk.c +++ b/src/pk.c @@ -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: diff --git a/src/ssl_certman.c b/src/ssl_certman.c index 3ea58740a5..eafa52ceb3 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -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; diff --git a/src/tls13.c b/src/tls13.c index 6d60d36143..e3671582ef 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -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; diff --git a/src/x509.c b/src/x509.c index c4a1285d65..c8332f77ae 100644 --- a/src/x509.c +++ b/src/x509.c @@ -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 diff --git a/testsuite/include.am b/testsuite/include.am index c96c79cbf8..5c750e6a3f 100644 --- a/testsuite/include.am +++ b/testsuite/include.am @@ -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) diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 26de7beb8b..0b48adbd17 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -51,6 +51,10 @@ #include #include #include +#if defined(HAVE_OCSP) && defined(HAVE_OCSP_RESPONDER) && \ + !defined(NO_FILESYSTEM) +#include +#endif #include /* 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)) diff --git a/testsuite/testsuite.vcproj b/testsuite/testsuite.vcproj index d30be1c110..c57907e306 100644 --- a/testsuite/testsuite.vcproj +++ b/testsuite/testsuite.vcproj @@ -189,6 +189,9 @@ + + diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f2da699476..5313f76c8e 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -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, diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 914a5e3dd0..3a32f915b7 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -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)) {