diff --git a/.gitignore b/.gitignore index 53606474d..1a17d53d4 100644 --- a/.gitignore +++ b/.gitignore @@ -369,3 +369,7 @@ IDE/XCODE/Index CMakeFiles/ CMakeCache.txt cmake_install.cmake + +# GDB Settings +\.gdbinit + diff --git a/configure.ac b/configure.ac index 1affa4a55..bc72485ea 100644 --- a/configure.ac +++ b/configure.ac @@ -778,6 +778,7 @@ AC_ARG_ENABLE([mcast], # openvpn (--enable-openvpn) WOLFSSL_OPENVPN # nginix (--enable-nginx) WOLFSSL_NGINX # ntp (--enable-ntp) +# openresty (--enable-openresty) # haproxy (--enable-haproxy) WOLFSSL_HAPROXY # wpa_supplicant (--enable-wpas) WOLFSSL_WPAS # ssl fortress (--enable-fortress) FORTRESS @@ -819,6 +820,13 @@ AC_ARG_ENABLE([openvpn], [ENABLED_OPENVPN=$enableval], [ENABLED_OPENVPN=no]) +# openresty compatibility build +AC_ARG_ENABLE([openresty], + [AS_HELP_STRING([--enable-openresty],[Enable openresty (default: disabled)])], + [ ENABLED_OPENRESTY=$enableval ], + [ ENABLED_OPENRESTY=no ] + ) + # nginx compatibility build AC_ARG_ENABLE([nginx], [AS_HELP_STRING([--enable-nginx],[Enable nginx (default: disabled)])], @@ -826,6 +834,11 @@ AC_ARG_ENABLE([nginx], [ ENABLED_NGINX=no ] ) +if test "$ENABLED_OPENRESTY" = "yes" +then + ENABLED_NGINX="yes" +fi + # lighty Support AC_ARG_ENABLE([lighty], [AS_HELP_STRING([--enable-lighty],[Enable lighttpd/lighty (default: disabled)])], @@ -965,7 +978,7 @@ AC_ARG_ENABLE([opensslall], [ ENABLED_OPENSSLALL=$enableval ], [ ENABLED_OPENSSLALL=no ] ) -if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_WPAS_DPP" = "yes" || test "$ENABLED_SMIME" = "yes" || test "$ENABLED_HAPROXY" = "yes" || test "$ENABLED_BIND" = "yes" || test "$ENABLED_NTP" == "yes" || test "$ENABLED_NETSNMP" = "yes" +if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_WPAS_DPP" = "yes" || test "$ENABLED_SMIME" = "yes" || test "$ENABLED_HAPROXY" = "yes" || test "$ENABLED_BIND" = "yes" || test "$ENABLED_NTP" == "yes" || test "$ENABLED_NETSNMP" = "yes" || test "$ENABLED_OPENRESTY" = "yes" then ENABLED_OPENSSLALL="yes" fi @@ -1910,7 +1923,7 @@ AC_ARG_ENABLE([keygen], [ ENABLED_KEYGEN=no ] ) -if test "$ENABLED_BIND" = "yes" || test "$ENABLED_NTP" = "yes" || test "$ENABLED_LIBSSH2" = "yes" +if test "$ENABLED_BIND" = "yes" || test "$ENABLED_NTP" = "yes" || test "$ENABLED_LIBSSH2" = "yes" || test "$ENABLED_OPENRESTY" = "yes" then ENABLED_KEYGEN=yes fi @@ -6998,6 +7011,7 @@ echo " * libssh2: $ENABLED_LIBSSH2" echo " * ntp: $ENABLED_NTP" echo " * Apache httpd: $ENABLED_APACHE_HTTPD" echo " * NGINX: $ENABLED_NGINX" +echo " * OpenResty: $ENABLED_OPENRESTY" echo " * ASIO: $ENABLED_ASIO" echo " * LIBWEBSOCKETS: $ENABLED_LIBWEBSOCKETS" echo " * Qt: $ENABLED_QT" diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index fb87141f8..31f7c1fea 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -9358,7 +9358,7 @@ WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*); int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor); … - wolfSSL_CertManagerLoadCRL(ssl->ctx->cm, path, type, monitor); + wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor); \endcode \sa wolfSSL_CertManagerEnableCRL @@ -9434,7 +9434,7 @@ WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*, CbMissingCRL cb = CbMissingCRL; … if(ctx){ - return wolfSSL_CertManagerSetCRL_Cb(ssl->ctx->cm, cb); + return wolfSSL_CertManagerSetCRL_Cb(SSL_CM(ssl), cb); } \endcode @@ -9505,7 +9505,7 @@ WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*, WOLFSSL_CERT_MANAGER* cm = wolfSSL_CertManagerNew(); int options; … - if(wolfSSL_CertManagerEnableOCSP(ssl->ctx->cm, options) != SSL_SUCCESS){ + if(wolfSSL_CertManagerEnableOCSP(SSL_CM(ssl), options) != SSL_SUCCESS){ Failure case. } \endcode @@ -9561,7 +9561,7 @@ WOLFSSL_API int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER*); … int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url) … - if(wolfSSL_CertManagerSetOCSPOverrideURL(ssl->ctx->cm, url) != SSL_SUCCESS){ + if(wolfSSL_CertManagerSetOCSPOverrideURL(SSL_CM(ssl), url) != SSL_SUCCESS){ Failure case. } \endcode @@ -9593,7 +9593,7 @@ WOLFSSL_API int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER*, wolfSSL_SetOCSP_Cb(WOLFSSL* ssl, CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx){ … - return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm, ioCb, respFreeCb, ioCbCtx); + return wolfSSL_CertManagerSetOCSP_Cb(SSL_CM(ssl), ioCb, respFreeCb, ioCbCtx); \endcode \sa wolfSSL_CertManagerSetOCSPOverrideURL diff --git a/src/internal.c b/src/internal.c index ef50c2137..720085a9e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2114,6 +2114,7 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) return ret; } + #ifdef HAVE_EX_DATA_CLEANUP_HOOKS void wolfSSL_CRYPTO_cleanup_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data) { @@ -3764,8 +3765,10 @@ void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap) x509->dynamicMemory = (byte)dynamicFlag; #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) x509->refCount = 1; + #ifndef SINGLE_THREADED (void)wc_InitMutex(&x509->refMutex); #endif + #endif } @@ -3844,8 +3847,10 @@ void FreeX509(WOLFSSL_X509* x509) } #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + #ifndef SINGLE_THREADED wc_FreeMutex(&x509->refMutex); #endif + #endif } @@ -6981,6 +6986,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) if (ssl->nxCtx.nxPacket) nx_packet_release(ssl->nxCtx.nxPacket); #endif +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + if (ssl->x509_store_pt) + wolfSSL_X509_STORE_free(ssl->x509_store_pt); +#endif #ifdef KEEP_PEER_CERT FreeX509(&ssl->peerCert); #endif @@ -7064,6 +7073,7 @@ void SSL_ResourceFree(WOLFSSL* ssl) #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) wolfSSL_sk_CIPHER_free(ssl->supportedCiphers); wolfSSL_sk_X509_free(ssl->peerCertChain); + wolfSSL_sk_X509_free(ssl->ourCertChain); #endif } @@ -10711,7 +10721,7 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap); - if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) + if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0) != 0) ret = BAD_CERTIFICATE_STATUS_ERROR; else if (CompareOcspReqResp(request, response) != 0) ret = BAD_CERTIFICATE_STATUS_ERROR; @@ -11003,12 +11013,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, if (ssl != NULL) { #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - if (ssl->ctx->x509_store_pt != NULL) { - store->store = ssl->ctx->x509_store_pt; - } - else { - store->store = &ssl->ctx->x509_store; - } + store->store = SSL_STORE(ssl); #if defined(OPENSSL_EXTRA) store->depth = args->count; store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( @@ -11424,7 +11429,7 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, /* perform cert parsing and signature check */ sigRet = CheckCertSignature(cert->buffer, cert->length, - ssl->heap, ssl->ctx->cm); + ssl->heap, SSL_CM(ssl)); /* fail on errors here after the ParseCertRelative call, so dCert is populated */ /* verify name only in ParseCertRelative below, signature check done */ @@ -11466,7 +11471,7 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, } /* Parse Certificate */ - ret = ParseCertRelative(args->dCert, certType, verify, ssl->ctx->cm); + ret = ParseCertRelative(args->dCert, certType, verify, SSL_CM(ssl)); /* perform below checks for date failure cases */ if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) { /* get subject and determine if already loaded */ @@ -11476,7 +11481,7 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, else #endif subjectHash = args->dCert->subjectHash; - alreadySigner = AlreadySigner(ssl->ctx->cm, subjectHash); + alreadySigner = AlreadySigner(SSL_CM(ssl), subjectHash); } #ifdef WOLFSSL_SMALL_CERT_VERIFY @@ -11851,7 +11856,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (args->dCert->extAuthKeyIdSet) matchType = WC_MATCH_SKID; #endif - tp = GetTrustedPeer(ssl->ctx->cm, subjectHash, matchType); + tp = GetTrustedPeer(SSL_CM(ssl), subjectHash, matchType); WOLFSSL_MSG("Checking for trusted peer cert"); if (tp && MatchTrustedPeer(tp, args->dCert)) { @@ -11895,15 +11900,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) if (ret == ASN_NO_SIGNER_E) { WOLFSSL_MSG("try to load certificate if hash dir is set"); - if (ssl->ctx->x509_store_pt != NULL) { - ret = LoadCertByIssuer(ssl->ctx->x509_store_pt, - (WOLFSSL_X509_NAME*)args->dCert->issuerName, - X509_LU_X509); - } else { - ret = LoadCertByIssuer(&ssl->ctx->x509_store, - (WOLFSSL_X509_NAME*)args->dCert->issuerName, - X509_LU_X509); - } + ret = LoadCertByIssuer(SSL_STORE(ssl), + (WOLFSSL_X509_NAME*)args->dCert->issuerName, + X509_LU_X509); if (ret == WOLFSSL_SUCCESS) { FreeDecodedCert(args->dCert); args->dCertInit = 0; @@ -11960,10 +11959,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } else /* skips OCSP and force CRL check */ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ - if (ssl->ctx->cm->ocspEnabled && - ssl->ctx->cm->ocspCheckAll) { + if (SSL_CM(ssl)->ocspEnabled && + SSL_CM(ssl)->ocspCheckAll) { WOLFSSL_MSG("Doing Non Leaf OCSP check"); - ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp, + ret = CheckCertOCSP_ex(SSL_CM(ssl)->ocsp, args->dCert, NULL, ssl); #ifdef WOLFSSL_NONBLOCK_OCSP if (ret == OCSP_WANT_READ) { @@ -11981,10 +11980,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef HAVE_CRL if (ret == 0 && doCrlLookup && - ssl->ctx->cm->crlEnabled && - ssl->ctx->cm->crlCheckAll) { + SSL_CM(ssl)->crlEnabled && + SSL_CM(ssl)->crlCheckAll) { WOLFSSL_MSG("Doing Non Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + ret = CheckCertCRL(SSL_CM(ssl)->crl, args->dCert); #ifdef WOLFSSL_NONBLOCK_OCSP if (ret == OCSP_WANT_READ) { args->lastErr = ret; @@ -12010,7 +12009,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif /* Do verify callback */ - ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args); + ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args); if (ssl->options.verifyNone && (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); @@ -12061,7 +12060,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* CA already verified above in ParseCertRelative */ WOLFSSL_MSG("Adding CA from chain"); - ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, + ret = AddCA(SSL_CM(ssl), &add, WOLFSSL_CHAIN_CA, NO_VERIFY); if (ret == WOLFSSL_SUCCESS) { ret = 0; @@ -12115,15 +12114,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) if (ret == ASN_NO_SIGNER_E) { WOLFSSL_MSG("try to load certificate if hash dir is set"); - if (ssl->ctx->x509_store_pt != NULL) { - ret = LoadCertByIssuer(ssl->ctx->x509_store_pt, - (WOLFSSL_X509_NAME*)args->dCert->issuerName, - X509_LU_X509); - } else { - ret = LoadCertByIssuer(&ssl->ctx->x509_store, - (WOLFSSL_X509_NAME*)args->dCert->issuerName, - X509_LU_X509); - } + ret = LoadCertByIssuer(SSL_STORE(ssl), + (WOLFSSL_X509_NAME*)args->dCert->issuerName, + X509_LU_X509); if (ret == WOLFSSL_SUCCESS) { FreeDecodedCert(args->dCert); args->dCertInit = 0; @@ -12286,7 +12279,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } /* Ensure a stapling response was seen */ else if (ssl->options.tls1_3 && - ssl->ctx->cm->ocspMustStaple) { + SSL_CM(ssl)->ocspMustStaple) { ret = OCSP_CERT_UNKNOWN; goto exit_ppc; } @@ -12301,9 +12294,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #ifdef HAVE_OCSP - if (doLookup && ssl->ctx->cm->ocspEnabled) { + if (doLookup && SSL_CM(ssl)->ocspEnabled) { WOLFSSL_MSG("Doing Leaf OCSP check"); - ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp, + ret = CheckCertOCSP_ex(SSL_CM(ssl)->ocsp, args->dCert, NULL, ssl); #ifdef WOLFSSL_NONBLOCK_OCSP if (ret == OCSP_WANT_READ) { @@ -12328,9 +12321,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif /* HAVE_OCSP */ #ifdef HAVE_CRL - if (doLookup && ssl->ctx->cm->crlEnabled) { + if (doLookup && SSL_CM(ssl)->crlEnabled) { WOLFSSL_MSG("Doing Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + ret = CheckCertCRL(SSL_CM(ssl)->crl, args->dCert); #ifdef WOLFSSL_NONBLOCK_OCSP if (ret == OCSP_WANT_READ) { goto exit_ppc; @@ -12795,7 +12788,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif /* Do verify callback */ - ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args); + ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args); if (ssl->options.verifyNone && (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { @@ -13012,7 +13005,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap); - if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, + if ((OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0) != 0) || (response->responseStatus != OCSP_SUCCESSFUL) || (response->single->status->status != CERT_GOOD)) @@ -13414,7 +13407,7 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 !ssl->status_request_v2 && #endif - ssl->ctx->cm->ocspMustStaple) { + SSL_CM(ssl)->ocspMustStaple) { return OCSP_CERT_UNKNOWN; } #endif @@ -16066,6 +16059,12 @@ const char* AlertTypeToString(int type) } #endif + case internal_error: + { + static const char internal_error_str[] = + "internal_error"; + return internal_error_str; + } case no_renegotiation: { static const char no_renegotiation_str[] = @@ -18263,7 +18262,7 @@ static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request, InitDecodedCert(cert, certData, length, ssl->heap); /* TODO: Setup async support here */ - ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm); + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, SSL_CM(ssl)); if (ret != 0) { WOLFSSL_MSG("ParseCert failed"); } @@ -18272,7 +18271,7 @@ static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request, if (ret == 0) { /* make sure ctx OCSP request is updated */ if (!ssl->buffers.weOwnCert) { - wolfSSL_Mutex* ocspLock = &ssl->ctx->cm->ocsp_stapling->ocspLock; + wolfSSL_Mutex* ocspLock = &SSL_CM(ssl)->ocsp_stapling->ocspLock; if (wc_LockMutex(ocspLock) == 0) { if (ssl->ctx->certOcspRequest == NULL) ssl->ctx->certOcspRequest = request; @@ -18312,7 +18311,7 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest, request = *ocspRequest; /* unable to fetch status. skip. */ - if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) + if (SSL_CM(ssl) == NULL || SSL_CM(ssl)->ocspStaplingEnabled == 0) return 0; if (request == NULL || ssl->buffers.weOwnCert) { @@ -18356,7 +18355,7 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest, if (ret == 0) { request->ssl = ssl; - ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, response); + ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling, request, response); /* Suppressing, not critical */ if (ret == OCSP_CERT_REVOKED || @@ -19072,8 +19071,8 @@ int SendCertificateStatus(WOLFSSL* ssl) der.length); if (ret == 0) { request->ssl = ssl; - ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, - request, &responses[i + 1]); + ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling, + request, &responses[i + 1]); /* Suppressing, not critical */ if (ret == OCSP_CERT_REVOKED || @@ -19098,7 +19097,7 @@ int SendCertificateStatus(WOLFSSL* ssl) while (ret == 0 && NULL != (request = ssl->ctx->chainOcspRequest[i])) { request->ssl = ssl; - ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, + ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling, request, &responses[++i]); /* Suppressing, not critical */ @@ -22952,6 +22951,8 @@ exit_dpk: return WOLFSSL_ERROR_WANT_X509_LOOKUP; } } + if ((ret = CertSetupCbWrapper(ssl)) != 0) + return ret; #endif /* don't send client cert or cert verify if user hasn't provided @@ -29691,6 +29692,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, wc_HmacFree(&cookieHmac); #endif +#ifdef OPENSSL_EXTRA + if (ret == 0) + ret = CertSetupCbWrapper(ssl); +#endif + return ret; } diff --git a/src/ssl.c b/src/ssl.c index bd8bfdd46..24656a7a4 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3816,11 +3816,13 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap) wolfSSL_CertManagerFree(cm); return NULL; } + #ifndef SINGLE_THREADED if (wc_InitMutex(&cm->refMutex) != 0) { WOLFSSL_MSG("Bad mutex init"); wolfSSL_CertManagerFree(cm); return NULL; } + #endif #ifdef WOLFSSL_TRUST_PEER_CERT if (wc_InitMutex(&cm->tpLock) != 0) { @@ -3856,13 +3858,17 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) WOLFSSL_ENTER("wolfSSL_CertManagerFree"); if (cm) { + #ifndef SINGLE_THREADED if (wc_LockMutex(&cm->refMutex) != 0) { WOLFSSL_MSG("Couldn't lock cm mutex"); } + #endif cm->refCount--; if (cm->refCount == 0) doFree = 1; + #ifndef SINGLE_THREADED wc_UnLockMutex(&cm->refMutex); + #endif if (doFree) { #ifdef HAVE_CRL if (cm->crl) @@ -3886,9 +3892,11 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap); wc_FreeMutex(&cm->tpLock); #endif + #ifndef SINGLE_THREADED if (wc_FreeMutex(&cm->refMutex) != 0) { WOLFSSL_MSG("Couldn't free refMutex mutex"); } + #endif XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER); } } @@ -3898,11 +3906,15 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm) { if (cm) { +#ifndef SINGLE_THREADED if (wc_LockMutex(&cm->refMutex) != 0) { WOLFSSL_MSG("Failed to lock cm mutex"); } +#endif cm->refCount++; +#ifndef SINGLE_THREADED wc_UnLockMutex(&cm->refMutex); +#endif return WOLFSSL_SUCCESS; } @@ -6183,7 +6195,7 @@ int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, if (ssl == NULL || ssl->ctx == NULL) return BAD_FUNC_ARG; - return wolfSSL_CertManagerLoadCRLBuffer(ssl->ctx->cm, buff, sz, type); + return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type); } @@ -6625,7 +6637,7 @@ int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options) { WOLFSSL_ENTER("wolfSSL_EnableOCSP"); if (ssl) - return wolfSSL_CertManagerEnableOCSP(ssl->ctx->cm, options); + return wolfSSL_CertManagerEnableOCSP(SSL_CM(ssl), options); else return BAD_FUNC_ARG; } @@ -6634,7 +6646,7 @@ int wolfSSL_DisableOCSP(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_DisableOCSP"); if (ssl) - return wolfSSL_CertManagerDisableOCSP(ssl->ctx->cm); + return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl)); else return BAD_FUNC_ARG; } @@ -6644,7 +6656,7 @@ int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling"); if (ssl) - return wolfSSL_CertManagerEnableOCSPStapling(ssl->ctx->cm); + return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl)); else return BAD_FUNC_ARG; } @@ -6653,7 +6665,7 @@ int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling"); if (ssl) - return wolfSSL_CertManagerDisableOCSPStapling(ssl->ctx->cm); + return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl)); else return BAD_FUNC_ARG; } @@ -6662,7 +6674,7 @@ int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url) { WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL"); if (ssl) - return wolfSSL_CertManagerSetOCSPOverrideURL(ssl->ctx->cm, url); + return wolfSSL_CertManagerSetOCSPOverrideURL(SSL_CM(ssl), url); else return BAD_FUNC_ARG; } @@ -6674,7 +6686,7 @@ int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl, WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb"); if (ssl) { ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */ - return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm, + return wolfSSL_CertManagerSetOCSP_Cb(SSL_CM(ssl), ioCb, respFreeCb, NULL); } else @@ -7206,7 +7218,7 @@ int wolfSSL_EnableCRL(WOLFSSL* ssl, int options) { WOLFSSL_ENTER("wolfSSL_EnableCRL"); if (ssl) - return wolfSSL_CertManagerEnableCRL(ssl->ctx->cm, options); + return wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), options); else return BAD_FUNC_ARG; } @@ -7216,7 +7228,7 @@ int wolfSSL_DisableCRL(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_DisableCRL"); if (ssl) - return wolfSSL_CertManagerDisableCRL(ssl->ctx->cm); + return wolfSSL_CertManagerDisableCRL(SSL_CM(ssl)); else return BAD_FUNC_ARG; } @@ -7226,7 +7238,7 @@ int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor) { WOLFSSL_ENTER("wolfSSL_LoadCRL"); if (ssl) - return wolfSSL_CertManagerLoadCRL(ssl->ctx->cm, path, type, monitor); + return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor); else return BAD_FUNC_ARG; } @@ -7237,7 +7249,7 @@ int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb) { WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); if (ssl) - return wolfSSL_CertManagerSetCRL_Cb(ssl->ctx->cm, cb); + return wolfSSL_CertManagerSetCRL_Cb(SSL_CM(ssl), cb); else return BAD_FUNC_ARG; } @@ -7247,7 +7259,7 @@ int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb) { WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); if (ssl) - return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb); + return wolfSSL_CertManagerSetCRL_IOCb(SSL_CM(ssl), cb); else return BAD_FUNC_ARG; } @@ -13596,24 +13608,35 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, /* in case used set_accept_state after init */ /* allow no private key if using PK callbacks and CB is set */ if (!havePSK && !haveAnon && !haveMcast) { - if (!ssl->buffers.certificate || - !ssl->buffers.certificate->buffer) { - - WOLFSSL_MSG("accept error: server cert required"); - WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); - return WOLFSSL_FATAL_ERROR; - } - - #ifdef HAVE_PK_CALLBACKS - if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { - WOLFSSL_MSG("Using PK for server private key"); + #ifdef OPENSSL_EXTRA + if (ssl->ctx->certSetupCb != NULL) { + WOLFSSL_MSG("CertSetupCb set. server cert and " + "key not checked"); } else #endif - if (!ssl->buffers.key || !ssl->buffers.key->buffer) { - WOLFSSL_MSG("accept error: server key required"); - WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); - return WOLFSSL_FATAL_ERROR; + { + if (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer) { + + WOLFSSL_MSG("accept error: server cert required"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for server private key"); + } + else + #endif + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("accept error: server key required"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } } } #endif @@ -16073,8 +16096,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #endif /* SESSION_CERTS */ - #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ - defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + #ifdef OPENSSL_EXTRA /* registers client cert callback, called during handshake if server requests client auth but user has not loaded client cert/key */ void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb) @@ -16085,7 +16107,48 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ctx->CBClientCert = cb; } } - #endif /* OPENSSL_ALL || OPENSSL_EXTRA || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + + void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx, + CertSetupCallback cb, void *arg) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_cert_cb"); + if (ctx == NULL) + return; + + ctx->certSetupCb = cb; + ctx->certSetupCbArg = arg; + } + + /** + * Internal wrapper for calling certSetupCb + * @param ssl + * @return 0 on success + */ + int CertSetupCbWrapper(WOLFSSL* ssl) + { + int ret = 0; + if (ssl->ctx->certSetupCb != NULL) { + WOLFSSL_MSG("Calling user cert setup callback"); + ret = ssl->ctx->certSetupCb(ssl, ssl->ctx->certSetupCbArg); + if (ret == 1) { + WOLFSSL_MSG("User cert callback returned success"); + ret = 0; + } + else if (ret == 0) { + SendAlert(ssl, alert_fatal, internal_error); + ret = CLIENT_CERT_CB_ERROR; + } + else if (ret < 0) { + ret = WOLFSSL_ERROR_WANT_X509_LOOKUP; + } + else { + WOLFSSL_MSG("Unexpected user callback return"); + ret = CLIENT_CERT_CB_ERROR; + } + } + return ret; + } + #endif /* OPENSSL_EXTRA */ #endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */ @@ -16599,17 +16662,72 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #endif /* OPENSSL_EXTRA */ #if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + /** + * Implemented in a similar way that ngx_ssl_ocsp_validate does it when + * SSL_get0_verified_chain is not available. + * @param ssl WOLFSSL object to extract certs from + * @return Stack of verified certs + */ + WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) + { + WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; + WOLFSSL_X509_STORE_CTX* storeCtx = NULL; + WOLFSSL_X509* peerCert = NULL; + + WOLFSSL_ENTER("wolfSSL_get0_verified_chain"); + + if (ssl == NULL || ssl->ctx == NULL) { + WOLFSSL_MSG("Bad parameter"); + return NULL; + } + + peerCert = wolfSSL_get_peer_certificate((WOLFSSL*)ssl); + if (peerCert == NULL) { + WOLFSSL_MSG("wolfSSL_get_peer_certificate error"); + return NULL; + } + chain = wolfSSL_get_peer_cert_chain(ssl); + if (chain == NULL) { + WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); + return NULL; + } + storeCtx = wolfSSL_X509_STORE_CTX_new(); + if (storeCtx == NULL) { + WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error"); + return NULL; + } + if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl), + peerCert, chain) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error"); + wolfSSL_X509_STORE_CTX_free(storeCtx); + return NULL; + } + if (wolfSSL_X509_verify_cert(storeCtx) <= 0) { + WOLFSSL_MSG("wolfSSL_X509_verify_cert error"); + wolfSSL_X509_STORE_CTX_free(storeCtx); + return NULL; + } + wolfSSL_X509_STORE_CTX_free(storeCtx); + return chain; + } +#endif /* SESSION_CERTS && OPENSSL_EXTRA */ + WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx) { if (ctx == NULL) { return NULL; } + if (ctx->x509_store_pt != NULL) + return ctx->x509_store_pt; return &ctx->x509_store; } void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) { + WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store"); if (ctx == NULL || str == NULL || ctx->cm == str->cm) { return; } @@ -16635,6 +16753,59 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) + { + WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store"); + + if (ssl == NULL || str == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + + /* NO-OP when setting existing store */ + if (str == SSL_STORE(ssl)) + return WOLFSSL_SUCCESS; + + /* free existing store if it exists */ + wolfSSL_X509_STORE_free(ssl->x509_store_pt); + if (str == ssl->ctx->x509_store_pt) + ssl->x509_store_pt = NULL; /* if setting ctx store then just revert + to using that instead */ + else + ssl->x509_store_pt = str; /* take ownership of store and free it + with SSL free */ + return WOLFSSL_SUCCESS; + } + + + int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) + { + WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store"); + + if (ssl == NULL || str == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + + /* NO-OP when setting existing store */ + if (str == SSL_STORE(ssl)) + return WOLFSSL_SUCCESS; + + if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); + return WOLFSSL_FAILURE; + } + + /* free existing store if it exists */ + wolfSSL_X509_STORE_free(ssl->x509_store_pt); + if (str == ssl->ctx->x509_store_pt) + ssl->x509_store_pt = NULL; /* if setting ctx store then just revert + to using that instead */ + else + ssl->x509_store_pt = str; /* take ownership of store and free it + with SSL free */ + return WOLFSSL_SUCCESS; + } #endif /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */ #ifdef WOLFSSL_ENCRYPTED_KEYS @@ -17415,6 +17586,22 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, else return 0; } + + unsigned char *wolfSSL_MD5(const unsigned char* data, size_t len, + unsigned char* hash) + { + static unsigned char out[WC_MD5_DIGEST_SIZE]; + + WOLFSSL_ENTER("wolfSSL_MD5"); + + if (hash == NULL) + hash = out; + if (wc_Md5Hash(data, (word32)len, hash) != 0) { + WOLFSSL_MSG("wc_Md5Hash error"); + return NULL; + } + return hash; + } #endif /* !NO_MD5 */ @@ -18833,7 +19020,7 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, } } #endif - return 0; + return NULL; } #endif /* KEEP_PEER_CERT */ @@ -18854,6 +19041,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) return ssl->peerCertChain; } +#ifndef WOLFSSL_QT static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, WOLFSSL_X509 *x); /** @@ -18865,7 +19053,7 @@ static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, * WOLFSSL_FAILURE on no issuer found * WOLFSSL_FATAL_ERROR on a fatal error */ -static int pushCAx509Chain(WOLFSSL_CERT_MANAGER* cm, +static int PushCAx509Chain(WOLFSSL_CERT_MANAGER* cm, WOLFSSL_X509 *x, WOLFSSL_STACK* sk) { WOLFSSL_X509* issuer[MAX_CHAIN_DEPTH]; @@ -18896,6 +19084,7 @@ static int pushCAx509Chain(WOLFSSL_CERT_MANAGER* cm, } return ret; } +#endif /* !WOLFSSL_QT */ /* Builds up and creates a stack of peer certificates for ssl->peerCertChain based off of the ssl session chain. Attempts to place CA certificates @@ -18927,13 +19116,11 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) if (ret == 0 && i == ssl->session.chain.count-1) { /* On the last element in the chain try to add the CA chain * first if we have one for this cert */ - if (pushCAx509Chain(ssl->ctx->cm, x509, sk) + if (PushCAx509Chain(SSL_CM(ssl), x509, sk) == WOLFSSL_FATAL_ERROR) { ret = WOLFSSL_FATAL_ERROR; } } -#else - (void)pushCAx509Chain; #endif if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { @@ -18979,14 +19166,18 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) #endif if (x509->dynamicMemory) { #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) + #ifndef SINGLE_THREADED if (wc_LockMutex(&x509->refMutex) != 0) { WOLFSSL_MSG("Couldn't lock x509 mutex"); } + #endif /* only free if all references to it are done */ x509->refCount--; if (x509->refCount == 0) doFree = 1; + #ifndef SINGLE_THREADED wc_UnLockMutex(&x509->refMutex); + #endif #endif /* OPENSSL_EXTRA_X509_SMALL || OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) @@ -21494,11 +21685,13 @@ WOLFSSL_SESSION* wolfSSL_SESSION_new(void) #ifdef OPENSSL_EXTRA if (ret != NULL) { +#ifndef SINGLE_THREADED if (wc_InitMutex(&ret->refMutex) != 0) { WOLFSSL_MSG("Error setting up session reference mutex"); XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); return NULL; } +#endif ret->refCount = 1; } #endif @@ -21514,11 +21707,15 @@ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) return WOLFSSL_FAILURE; #ifdef OPENSSL_EXTRA +#ifndef SINGLE_THREADED if (wc_LockMutex(&session->refMutex) != 0) { WOLFSSL_MSG("Failed to lock session mutex"); } +#endif session->refCount++; +#ifndef SINGLE_THREADED wc_UnLockMutex(&session->refMutex); +#endif #endif return WOLFSSL_SUCCESS; } @@ -21545,11 +21742,13 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) XMEMCPY(copy, session, sizeof(WOLFSSL_SESSION)); copy->isAlloced = 1; #ifdef OPENSSL_EXTRA +#ifndef SINGLE_THREADED if (wc_InitMutex(©->refMutex) != 0) { WOLFSSL_MSG("Error setting up session reference mutex"); XFREE(copy, NULL, DYNAMIC_TYPE_OPENSSL); return NULL; } +#endif copy->refCount = 1; #endif #ifdef HAVE_SESSION_TICKET @@ -21594,15 +21793,21 @@ void FreeSession(WOLFSSL_SESSION* session, int isAlloced) /* refCount will always be 1 or more if created externally. * Internal cache sessions don't initialize a refMutex. */ if (session->refCount > 0) { +#ifndef SINGLE_THREADED if (wc_LockMutex(&session->refMutex) != 0) { WOLFSSL_MSG("Failed to lock session mutex"); } +#endif if (session->refCount > 1) { session->refCount--; +#ifndef SINGLE_THREADED wc_UnLockMutex(&session->refMutex); +#endif return; } +#ifndef SINGLE_THREADED wc_UnLockMutex(&session->refMutex); +#endif } #endif #if defined(HAVE_EXT_CACHE) || defined(OPENSSL_EXTRA) @@ -26745,6 +26950,16 @@ long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) } } + +long wolfSSL_get_tlsext_status_type(WOLFSSL *s) +{ + TLSX* extension; + + if (s == NULL) + return WOLFSSL_FATAL_ERROR; + extension = TLSX_Find(s->extensions, TLSX_STATUS_REQUEST); + return extension != NULL ? TLSEXT_STATUSTYPE_ocsp : WOLFSSL_FATAL_ERROR; +} #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ #ifndef NO_WOLFSSL_STUB @@ -38957,11 +39172,15 @@ int wolfSSL_DH_LoadDer(WOLFSSL_DH* dh, const unsigned char* derBuf, int derSz) int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa) { if (rsa) { +#ifndef SINGLE_THREADED if (wc_LockMutex(&rsa->refMutex) != 0) { WOLFSSL_MSG("Failed to lock x509 mutex"); } +#endif rsa->refCount++; +#ifndef SINGLE_THREADED wc_UnLockMutex(&rsa->refMutex); +#endif return WOLFSSL_SUCCESS; } @@ -38973,11 +39192,15 @@ int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa) int wolfSSL_X509_up_ref(WOLFSSL_X509* x509) { if (x509) { +#ifndef SINGLE_THREADED if (wc_LockMutex(&x509->refMutex) != 0) { WOLFSSL_MSG("Failed to lock x509 mutex"); } +#endif x509->refCount++; +#ifndef SINGLE_THREADED wc_UnLockMutex(&x509->refMutex); +#endif return WOLFSSL_SUCCESS; } @@ -42489,19 +42712,157 @@ err: return WOLFSSL_SUCCESS; } + static int PushCertToDerBuffer(DerBuffer** inOutDer, int weOwn, + byte* cert, word32 certSz, void* heap) + { + int ret; + DerBuffer* inChain = NULL; + DerBuffer* der = NULL; + word32 len = 0; + if (inOutDer == NULL) + return BAD_FUNC_ARG; + inChain = *inOutDer; + if (inChain != NULL) + len = inChain->length; + ret = AllocDer(&der, len + CERT_HEADER_SZ + certSz, CERT_TYPE, + heap); + if (ret != 0) { + WOLFSSL_MSG("AllocDer error"); + return ret; + } + if (inChain != NULL) + XMEMCPY(der->buffer, inChain->buffer, len); + c32to24(certSz, der->buffer + len); + XMEMCPY(der->buffer + len + CERT_HEADER_SZ, cert, certSz); + if (weOwn) + FreeDer(inOutDer); + *inOutDer = der; + return WOLFSSL_SUCCESS; + } + + /** + * wolfSSL_CTX_add1_chain_cert makes a copy of the cert so we free it + * on success + */ + int wolfSSL_CTX_add0_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_CTX_add0_chain_cert"); + if (wolfSSL_CTX_add1_chain_cert(ctx, x509) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + wolfSSL_X509_free(x509); + return WOLFSSL_SUCCESS; + } + int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) { int ret; + WOLFSSL_ENTER("wolfSSL_CTX_add1_chain_cert"); if (ctx == NULL || x509 == NULL || x509->derCert == NULL) { return WOLFSSL_FAILURE; } - ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer, - x509->derCert->length, WOLFSSL_FILETYPE_ASN1); + if (ctx->certificate == NULL) + ret = wolfSSL_CTX_use_certificate(ctx, x509); + else { + if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_up_ref error"); + return WOLFSSL_FAILURE; + } + ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer, + x509->derCert->length, WOLFSSL_FILETYPE_ASN1); + if (ret == WOLFSSL_SUCCESS) { + /* push to ctx->certChain */ + ret = PushCertToDerBuffer(&ctx->certChain, 1, + x509->derCert->buffer, x509->derCert->length, ctx->heap); + } + /* Store cert to free it later */ + if (ret == WOLFSSL_SUCCESS && ctx->x509Chain == NULL) { + ctx->x509Chain = wolfSSL_sk_X509_new(); + if (ctx->x509Chain == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_new error"); + ret = WOLFSSL_FAILURE; + } + } + if (ret == WOLFSSL_SUCCESS && + wolfSSL_sk_X509_push(ctx->x509Chain, x509) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_X509_push error"); + ret = WOLFSSL_FAILURE; + } + if (ret != WOLFSSL_SUCCESS) + wolfSSL_X509_free(x509); /* Decrease ref counter */ + } - return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } +#ifdef KEEP_OUR_CERT + int wolfSSL_add0_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509) + { + int ret; + + WOLFSSL_ENTER("wolfSSL_add0_chain_cert"); + + if (ssl == NULL || ssl->ctx == NULL || x509 == NULL || + x509->derCert == NULL) + return WOLFSSL_FAILURE; + + if (ssl->buffers.certificate == NULL) { + ret = wolfSSL_use_certificate(ssl, x509); + /* Store cert to free it later */ + if (ret == WOLFSSL_SUCCESS) { + if (ssl->buffers.weOwnCert) + wolfSSL_X509_free(ssl->ourCert); + ssl->ourCert = x509; + ssl->buffers.weOwnCert = 1; + } + } + else { + ret = PushCertToDerBuffer(&ssl->buffers.certChain, + ssl->buffers.weOwnCertChain, x509->derCert->buffer, + x509->derCert->length, ssl->heap); + if (ret == WOLFSSL_SUCCESS) { + ssl->buffers.weOwnCertChain = 1; + /* Store cert to free it later */ + if (ssl->ourCertChain == NULL) { + ssl->ourCertChain = wolfSSL_sk_X509_new(); + if (ssl->ourCertChain == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_new error"); + return WOLFSSL_FAILURE; + } + } + if (wolfSSL_sk_X509_push(ssl->ourCertChain, x509) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_X509_push error"); + return WOLFSSL_FAILURE; + } + } + } + return ret == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + } + + int wolfSSL_add1_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509) + { + int ret; + + WOLFSSL_ENTER("wolfSSL_add1_chain_cert"); + if (ssl == NULL || ssl->ctx == NULL || x509 == NULL || + x509->derCert == NULL) + return WOLFSSL_FAILURE; + + if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_up_ref error"); + return WOLFSSL_FAILURE; + } + ret = wolfSSL_add0_chain_cert(ssl, x509); + /* Decrease ref counter on error */ + if (ret != WOLFSSL_SUCCESS) + wolfSSL_X509_free(x509); + return ret; + } +#endif + /* Return the corresponding short name for the nid . * or NULL if short name can't be found. */ @@ -43766,6 +44127,35 @@ int wolfSSL_get_state(const WOLFSSL* ssl) } #endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ +#ifdef OPENSSL_EXTRA +void wolfSSL_certs_clear(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_certs_clear()"); + + if (ssl == NULL) + return; + + /* ctx still owns certificate, certChain, key, dh, and cm */ + if (ssl->buffers.weOwnCert) + FreeDer(&ssl->buffers.certificate); + ssl->buffers.certificate = NULL; + if (ssl->buffers.weOwnCertChain) + FreeDer(&ssl->buffers.certChain); + ssl->buffers.certChain = NULL; +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = 0; +#endif + if (ssl->buffers.weOwnKey) + FreeDer(&ssl->buffers.key); + ssl->buffers.key = NULL; + ssl->buffers.keyType = 0; + ssl->buffers.keyId = 0; + ssl->buffers.keyLabel = 0; + ssl->buffers.keySz = 0; + ssl->buffers.keyDevId = 0; +} +#endif + #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) @@ -47555,6 +47945,32 @@ int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb) return WOLFSSL_SUCCESS; } +int wolfSSL_CTX_get0_chain_certs(WOLFSSL_CTX *ctx, + WOLF_STACK_OF(WOLFSSL_X509) **sk) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get0_chain_certs"); + if (ctx == NULL || sk == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + *sk = ctx->x509Chain; + return WOLFSSL_SUCCESS; +} + +#ifdef KEEP_OUR_CERT +int wolfSSL_get0_chain_certs(WOLFSSL *ssl, + WOLF_STACK_OF(WOLFSSL_X509) **sk) +{ + WOLFSSL_ENTER("wolfSSL_get0_chain_certs"); + if (ssl == NULL || sk == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + *sk = ssl->ourCertChain; + return WOLFSSL_SUCCESS; +} +#endif + /** * Find the issuing cert of the input cert. On a self-signed cert this * function will return an error. @@ -51565,22 +51981,28 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) #endif #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) int doFree = 0; +#ifndef SINGLE_THREADED if (wc_LockMutex(&rsa->refMutex) != 0) { WOLFSSL_MSG("Couldn't lock rsa mutex"); } +#endif /* only free if all references to it are done */ rsa->refCount--; if (rsa->refCount == 0) { doFree = 1; } +#ifndef SINGLE_THREADED wc_UnLockMutex(&rsa->refMutex); +#endif if (!doFree) { return; } +#ifndef SINGLE_THREADED wc_FreeMutex(&rsa->refMutex); +#endif #endif if (rsa->internal) { @@ -51653,6 +52075,19 @@ WOLFSSL_RSA* wolfSSL_RSA_new(void) } InitwolfSSL_Rsa(external); + +#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) + external->refCount = 1; +#ifndef SINGLE_THREADED + if (wc_InitMutex(&external->refMutex) != 0) { + WOLFSSL_MSG("wc_InitMutex WOLFSSL_RSA failure"); + XFREE(external, NULL, DYNAMIC_TYPE_RSA); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; + } +#endif +#endif + if (wc_InitRsaKey(key, NULL) != 0) { WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure"); XFREE(external, NULL, DYNAMIC_TYPE_RSA); @@ -51693,10 +52128,6 @@ WOLFSSL_RSA* wolfSSL_RSA_new(void) external->internal = key; external->inSet = 0; -#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) - external->refCount = 1; - wc_InitMutex(&external->refMutex); -#endif return external; } #endif /* !NO_RSA && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ @@ -56810,9 +57241,10 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, ctx->current_cert = x509; #else if(x509 != NULL){ - ctx->current_cert = wolfSSL_X509_d2i(NULL, x509->derCert->buffer,x509->derCert->length); + ctx->current_cert = wolfSSL_X509_d2i(NULL, x509->derCert->buffer, + x509->derCert->length); if(ctx->current_cert == NULL) - return WOLFSSL_FATAL_ERROR; + return WOLFSSL_FAILURE; } else ctx->current_cert = NULL; #endif @@ -56824,7 +57256,7 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, if (x509_cert != NULL && x509_cert->isCa) { ret = wolfSSL_X509_STORE_add_cert(store, x509_cert); if (ret < 0) { - return WOLFSSL_FATAL_ERROR; + return WOLFSSL_FAILURE; } } sk = sk->next; @@ -56846,13 +57278,13 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, NULL,DYNAMIC_TYPE_OPENSSL); if (ctx->param == NULL){ WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FAILURE; } } #endif return WOLFSSL_SUCCESS; } - return WOLFSSL_FATAL_ERROR; + return WOLFSSL_FAILURE; } @@ -57301,9 +57733,7 @@ WOLFSSL_X509_STORE_CTX *wolfSSL_X509_STORE_CTX_get0_parent_ctx( WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_get0_parent_ctx"); return NULL; } -#endif -#ifndef NO_WOLFSSL_STUB int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx, WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj) { @@ -57316,6 +57746,7 @@ int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx, } #endif + #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) @@ -57398,93 +57829,6 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( } #endif /* WOLFSSL_SIGNER_DER_CERT */ -/****************************************************************************** -* wolfSSL_X509_STORE_GetCerts - retrieve stack of X509 in a certificate store ctx -* -* This API can be used in SSL verify callback function to view cert chain -* See examples/client/client.c and myVerify() function in test.h -* -* RETURNS: -* returns stack of X509 certs on success, otherwise returns a NULL. -*/ -WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s) -{ - int certIdx = 0; - WOLFSSL_BUFFER_INFO* cert = NULL; - DecodedCert* dCert = NULL; - WOLFSSL_X509* x509 = NULL; - WOLFSSL_STACK* sk = NULL; - int found = 0; - - if (s == NULL) { - return NULL; - } - - sk = wolfSSL_sk_X509_new(); - - if (sk == NULL) { - return NULL; - } - - for (certIdx = s->totalCerts - 1; certIdx >= 0; certIdx--) { - /* get certificate buffer */ - cert = &s->certs[certIdx]; - - dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); - - if (dCert == NULL) { - goto error; - } - XMEMSET(dCert, 0, sizeof(DecodedCert)); - - InitDecodedCert(dCert, cert->buffer, cert->length, NULL); - - /* Parse Certificate */ - if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, NULL)){ - goto error; - } - x509 = wolfSSL_X509_new(); - - if (x509 == NULL) { - goto error; - } - InitX509(x509, 1, NULL); - - if (CopyDecodedToX509(x509, dCert) == 0) { - - if (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Unable to load x509 into stack"); - wolfSSL_X509_free(x509); - goto error; - } - } - else { - goto error; - } - found = 1; - - FreeDecodedCert(dCert); - XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT); - dCert = NULL; - } - - if (!found) { - wolfSSL_sk_X509_free(sk); - sk = NULL; - } - return sk; - -error: - if (dCert) { - FreeDecodedCert(dCert); - XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT); - } - - if (sk) - wolfSSL_sk_X509_free(sk); - - return NULL; -} #endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */ #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ @@ -57532,6 +57876,12 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE)); store->isDynamic = 1; + store->refCount = 1; + +#ifndef SINGLE_THREADED + if (wc_InitMutex(&store->refMutex) != 0) + goto err_exit; +#endif if ((store->cm = wolfSSL_CertManagerNew()) == NULL) goto err_exit; @@ -57572,41 +57922,52 @@ err_exit: void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) { - if (store == NULL) - return; + int doFree = 0; + if (store != NULL && store->isDynamic) { +#ifndef SINGLE_THREADED + if (wc_LockMutex(&store->refMutex) != 0) { + WOLFSSL_MSG("Couldn't lock store mutex"); + } +#endif + store->refCount--; + if (store->refCount == 0) + doFree = 1; +#ifndef SINGLE_THREADED + wc_UnLockMutex(&store->refMutex); +#endif + if (doFree) { #ifdef HAVE_EX_DATA_CLEANUP_HOOKS - wolfSSL_CRYPTO_cleanup_ex_data(&store->ex_data); + wolfSSL_CRYPTO_cleanup_ex_data(&store->ex_data); #endif - - if (store->isDynamic) { - if (store->cm != NULL) { - wolfSSL_CertManagerFree(store->cm); - store->cm = NULL; - } + if (store->cm != NULL) { + wolfSSL_CertManagerFree(store->cm); + store->cm = NULL; + } #ifdef OPENSSL_ALL - if (store->objs != NULL) { - wolfSSL_sk_X509_OBJECT_free(store->objs); - } -#endif -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) - if (store->param != NULL) { - XFREE(store->param, NULL, DYNAMIC_TYPE_OPENSSL); - store->param = NULL; - } - - if (store->lookup.dirs != NULL) { -#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) - if (store->lookup.dirs->dir_entry) { - wolfSSL_sk_BY_DIR_entry_free(store->lookup.dirs->dir_entry); + if (store->objs != NULL) { + wolfSSL_sk_X509_OBJECT_free(store->objs); } #endif - wc_FreeMutex(&store->lookup.dirs->lock); - XFREE(store->lookup.dirs, NULL, DYNAMIC_TYPE_OPENSSL); - store->lookup.dirs = NULL; - } +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + if (store->param != NULL) { + XFREE(store->param, NULL, DYNAMIC_TYPE_OPENSSL); + store->param = NULL; + } + + if (store->lookup.dirs != NULL) { +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (store->lookup.dirs->dir_entry) { + wolfSSL_sk_BY_DIR_entry_free(store->lookup.dirs->dir_entry); + } #endif - XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); + wc_FreeMutex(&store->lookup.dirs->lock); + XFREE(store->lookup.dirs, NULL, DYNAMIC_TYPE_OPENSSL); + store->lookup.dirs = NULL; + } +#endif + XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); + } } } @@ -57630,6 +57991,25 @@ void* wolfSSL_X509_STORE_get_ex_data(WOLFSSL_X509_STORE* store, int idx) return NULL; } +int wolfSSL_X509_STORE_up_ref(WOLFSSL_X509_STORE* store) +{ + if (store) { +#ifndef SINGLE_THREADED + if (wc_LockMutex(&store->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock store mutex"); + } +#endif + store->refCount++; +#ifndef SINGLE_THREADED + wc_UnLockMutex(&store->refMutex); +#endif + + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + /** * Set ex_data for WOLFSSL_STORE * @param store a pointer to WOLFSSL_X509_STORE structure @@ -57890,6 +58270,95 @@ int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE* store) return cnt_ret; } +/****************************************************************************** +* wolfSSL_X509_STORE_GetCerts - retrieve stack of X509 in a certificate store ctx +* +* This API can be used in SSL verify callback function to view cert chain +* See examples/client/client.c and myVerify() function in test.h +* +* RETURNS: +* returns stack of X509 certs on success, otherwise returns a NULL. +*/ +WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s) +{ + int certIdx = 0; + WOLFSSL_BUFFER_INFO* cert = NULL; + DecodedCert* dCert = NULL; + WOLFSSL_X509* x509 = NULL; + WOLFSSL_STACK* sk = NULL; + int found = 0; + + if (s == NULL) { + return NULL; + } + + sk = wolfSSL_sk_X509_new(); + + if (sk == NULL) { + return NULL; + } + + for (certIdx = s->totalCerts - 1; certIdx >= 0; certIdx--) { + /* get certificate buffer */ + cert = &s->certs[certIdx]; + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + + if (dCert == NULL) { + goto error; + } + XMEMSET(dCert, 0, sizeof(DecodedCert)); + + InitDecodedCert(dCert, cert->buffer, cert->length, NULL); + + /* Parse Certificate */ + if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, NULL)){ + goto error; + } + x509 = wolfSSL_X509_new(); + + if (x509 == NULL) { + goto error; + } + InitX509(x509, 1, NULL); + + if (CopyDecodedToX509(x509, dCert) == 0) { + + if (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to load x509 into stack"); + wolfSSL_X509_free(x509); + goto error; + } + } + else { + goto error; + } + found = 1; + + FreeDecodedCert(dCert); + XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT); + dCert = NULL; + } + + if (!found) { + wolfSSL_sk_X509_free(sk); + sk = NULL; + } + return sk; + +error: + if (dCert) { + FreeDecodedCert(dCert); + XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT); + } + + if (sk) + wolfSSL_sk_X509_free(sk); + + return NULL; +} +#endif /* OPENSSL_EXTRA */ + #ifdef OPENSSL_ALL WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( WOLFSSL_X509_STORE* store) @@ -57970,8 +58439,6 @@ err_cleanup: } #endif /* OPENSSL_ALL */ -#endif /* OPENSSL_EXTRA */ - /******************************************************************************* * END OF X509_STORE APIs ******************************************************************************/ diff --git a/src/tls.c b/src/tls.c index 30b453b9b..17ceb3302 100644 --- a/src/tls.c +++ b/src/tls.c @@ -3118,7 +3118,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length, return BUFFER_ERROR; /* is able to send OCSP response? */ - if (ssl->ctx->cm == NULL || !ssl->ctx->cm->ocspStaplingEnabled) + if (SSL_CM(ssl) == NULL || !SSL_CM(ssl)->ocspStaplingEnabled) return 0; } break; @@ -3149,7 +3149,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length, } InitDecodedCert(cert, ssl->buffers.certificate->buffer, ssl->buffers.certificate->length, ssl->heap); - ret = ParseCert(cert, CERT_TYPE, 1, ssl->ctx->cm); + ret = ParseCert(cert, CERT_TYPE, 1, SSL_CM(ssl)); if (ret != 0 ) { XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); return ret; @@ -3241,9 +3241,9 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl) if (csr) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - if (ssl->ctx->cm->ocspEnabled) { + if (SSL_CM(ssl)->ocspEnabled) { csr->request.ocsp.ssl = ssl; - return CheckOcspRequest(ssl->ctx->cm->ocsp, + return CheckOcspRequest(SSL_CM(ssl)->ocsp, &csr->request.ocsp, NULL); } else @@ -3548,8 +3548,8 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, const byte* input, word16 length, return BUFFER_ERROR; /* is able to send OCSP response? */ - if (ssl->ctx->cm == NULL - || !ssl->ctx->cm->ocspStaplingEnabled) + if (SSL_CM(ssl) == NULL + || !SSL_CM(ssl)->ocspStaplingEnabled) continue; break; @@ -3669,9 +3669,9 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: - if (ssl->ctx->cm->ocspEnabled) { + if (SSL_CM(ssl)->ocspEnabled) { csr2->request.ocsp[0].ssl = ssl; - return CheckOcspRequest(ssl->ctx->cm->ocsp, + return CheckOcspRequest(SSL_CM(ssl)->ocsp, &csr2->request.ocsp[0], NULL); } else @@ -10680,7 +10680,7 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength) #endif #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) - if (!ssl->ctx->cm->ocspStaplingEnabled) { + if (!SSL_CM(ssl)->ocspStaplingEnabled) { /* mark already sent, so it won't send it */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2)); @@ -10781,7 +10781,7 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset) #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) /* mark already sent, so it won't send it */ - if (!ssl->ctx->cm->ocspStaplingEnabled) { + if (!SSL_CM(ssl)->ocspStaplingEnabled) { TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2)); } diff --git a/src/tls13.c b/src/tls13.c index 57cc20c22..e8b54595d 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3842,12 +3842,16 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, } *inOutIdx += len; - if (ssl->buffers.certificate && ssl->buffers.certificate->buffer && + if ((ssl->buffers.certificate && ssl->buffers.certificate->buffer && ((ssl->buffers.key && ssl->buffers.key->buffer) #ifdef HAVE_PK_CALLBACKS || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) #endif - )) { + )) + #ifdef OPENSSL_EXTRA + || ssl->ctx->certSetupCb != NULL + #endif + ) { if (PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, peerSuites.hashSigAlgoSz) != 0) { return INVALID_PARAMETER; @@ -5777,6 +5781,11 @@ static int SendTls13Certificate(WOLFSSL* ssl) listSz = 0; } else { +#ifdef OPENSSL_EXTRA + if ((ret = CertSetupCbWrapper(ssl)) != 0) + return ret; +#endif + if (!ssl->buffers.certificate) { WOLFSSL_MSG("Send Cert missing certificate buffer"); return BUFFER_ERROR; @@ -9223,24 +9232,34 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) if (!havePSK) #endif { - if (!ssl->buffers.certificate || - !ssl->buffers.certificate->buffer) { - - WOLFSSL_MSG("accept error: server cert required"); - WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); - return WOLFSSL_FATAL_ERROR; - } - - #ifdef HAVE_PK_CALLBACKS - if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { - WOLFSSL_MSG("Using PK for server private key"); + #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + if (ssl->ctx->certSetupCb != NULL) { + WOLFSSL_MSG("CertSetupCb set. server cert and " + "key not checked"); } else #endif - if (!ssl->buffers.key || !ssl->buffers.key->buffer) { - WOLFSSL_MSG("accept error: server key required"); - WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); - return WOLFSSL_FATAL_ERROR; + { + if (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer) { + + WOLFSSL_MSG("accept error: server cert required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } + + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for server private key"); + } + else + #endif + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("accept error: server key required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } } } #endif /* NO_CERTS */ diff --git a/tests/api.c b/tests/api.c index 9ba0f9dc4..cb6984e87 100644 --- a/tests/api.c +++ b/tests/api.c @@ -1791,6 +1791,49 @@ static void test_wolfSSL_CTX_load_verify_chain_buffer_format(void) #endif } +static void test_wolfSSL_CTX_add1_chain_cert(void) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && \ + defined(KEEP_OUR_CERT) + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + const char *certChain[] = { + "./certs/intermediate/client-int-cert.pem", + "./certs/intermediate/ca-int2-cert.pem", + "./certs/intermediate/ca-int-cert.pem", + "./certs/ca-cert.pem", + NULL + }; + const char** cert; + WOLFSSL_X509* x509; + WOLF_STACK_OF(X509)* chain = NULL; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + AssertNotNull(ssl = wolfSSL_new(ctx)); + + for (cert = certChain; *cert != NULL; cert++) { + x509 = wolfSSL_X509_load_certificate_file(*cert, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ(SSL_CTX_add1_chain_cert(ctx, x509), 1); + X509_free(x509); + } + for (cert = certChain; *cert != NULL; cert++) { + x509 = wolfSSL_X509_load_certificate_file(*cert, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ(SSL_add1_chain_cert(ssl, x509), 1); + X509_free(x509); + } + + AssertIntEQ(SSL_CTX_get0_chain_certs(ctx, &chain), 1); + AssertIntEQ(sk_X509_num(chain), 3); + AssertIntEQ(SSL_get0_chain_certs(ssl, &chain), 1); + AssertIntEQ(sk_X509_num(chain), 3); + + SSL_free(ssl); + SSL_CTX_free(ctx); +#endif +} + static int test_wolfSSL_CTX_use_certificate_chain_file_format(void) { int ret = 0; @@ -6416,7 +6459,7 @@ static void test_wolfSSL_PKCS12(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif /* Copy stack structure */ - AssertNotNull(tmp_ca = sk_X509_dup(ca)); + AssertNotNull(tmp_ca = X509_chain_up_ref(ca)); AssertIntEQ(SSL_CTX_set0_chain(ctx, tmp_ca), 1); /* CTX now owns the tmp_ca stack structure */ tmp_ca = NULL; @@ -7916,7 +7959,6 @@ static int test_wc_Md5Final (void) return flag; } - /* * Unit test for the wc_InitSha() */ @@ -31268,16 +31310,34 @@ static void test_wolfSSL_X509_STORE(void) #ifndef WOLFCRYPT_ONLY { SSL_CTX* ctx; - #ifndef NO_WOLFSSL_SERVER - AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); - #else - AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); - #endif - AssertNotNull(store = (X509_STORE *)X509_STORE_new()); - SSL_CTX_set_cert_store(ctx, store); - AssertNotNull(store = (X509_STORE *)X509_STORE_new()); - SSL_CTX_set_cert_store(ctx, store); - SSL_CTX_free(ctx); + SSL* ssl; + int i; + for (i = 0; i < 2; i++) { + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + AssertNotNull(store = (X509_STORE *)X509_STORE_new()); + SSL_CTX_set_cert_store(ctx, store); + AssertNotNull(store = (X509_STORE *)X509_STORE_new()); + SSL_CTX_set_cert_store(ctx, store); + AssertNotNull(store = (X509_STORE *)X509_STORE_new()); + AssertIntEQ(SSL_CTX_use_certificate_file(ctx, svrCertFile, + SSL_FILETYPE_PEM), SSL_SUCCESS); + AssertIntEQ(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, + SSL_FILETYPE_PEM), SSL_SUCCESS); + AssertNotNull(ssl = SSL_new(ctx)); + if (i == 0) { + AssertIntEQ(SSL_set0_verify_cert_store(ssl, store), SSL_SUCCESS); + } + else { + AssertIntEQ(SSL_set1_verify_cert_store(ssl, store), SSL_SUCCESS); + X509_STORE_free(store); + } + SSL_free(ssl); + SSL_CTX_free(ctx); + } } #endif printf(resultFmt, passed); @@ -31646,6 +31706,7 @@ static int msgCb(SSL_CTX *ctx, SSL *ssl) #if defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN) AssertTrue(SSL_get_peer_cert_chain(ssl) != NULL); AssertIntEQ(((WOLFSSL_X509_CHAIN *)SSL_get_peer_cert_chain(ssl))->count, 2); + AssertNotNull(SSL_get0_verified_chain(ssl)); #endif #if defined(OPENSSL_ALL) && defined(SESSION_CERTS) @@ -32175,8 +32236,9 @@ static void test_wolfSSL_set_tlsext_status_type(void){ AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); AssertNotNull(ssl = SSL_new(ctx)); - AssertTrue(SSL_set_tlsext_status_type(ssl,TLSEXT_STATUSTYPE_ocsp) - == SSL_SUCCESS); + AssertIntEQ(SSL_set_tlsext_status_type(ssl,TLSEXT_STATUSTYPE_ocsp), + SSL_SUCCESS); + AssertIntEQ(SSL_get_tlsext_status_type(ssl), TLSEXT_STATUSTYPE_ocsp); SSL_free(ssl); SSL_CTX_free(ctx); #endif /* OPENSSL_EXTRA && HAVE_CERTIFICATE_STATUS_REQUEST && !NO_RSA */ @@ -35498,6 +35560,122 @@ static void test_wolfSSL_BIO_f_md(void) #endif /* !NO_BIO */ +#if defined(OPENSSL_EXTRA) && defined(HAVE_IO_TESTS_DEPENDENCIES) + +/* test that the callback arg is correct */ +static int certCbArg = 0; + +static int clientCertCb(WOLFSSL* ssl, void* arg) +{ + if (ssl == NULL || arg != &certCbArg) + return 0; + if (wolfSSL_use_certificate_file(ssl, cliCertFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) + return 0; + if (wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) + return 0; + return 1; +} + +static void clientCertSetupCb(WOLFSSL_CTX* ctx) +{ + SSL_CTX_set_cert_cb(ctx, clientCertCb, &certCbArg); +} + +/** + * This is only done because test_client_nofail has no way to stop + * certificate and key loading + */ +static void clientCertClearCb(WOLFSSL* ssl) +{ + /* Clear the loaded certs to force the callbacks to set them up */ + SSL_certs_clear(ssl); +} + +static int serverCertCb(WOLFSSL* ssl, void* arg) +{ + if (ssl == NULL || arg != &certCbArg) + return 0; + if (wolfSSL_use_certificate_file(ssl, svrCertFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) + return 0; + if (wolfSSL_use_PrivateKey_file(ssl, svrKeyFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) + return 0; + return 1; +} + +static void serverCertSetupCb(WOLFSSL_CTX* ctx) +{ + SSL_CTX_set_cert_cb(ctx, serverCertCb, &certCbArg); +} + +/** + * This is only done because test_server_nofail has no way to stop + * certificate and key loading + */ +static void serverCertClearCb(WOLFSSL* ssl) +{ + /* Clear the loaded certs to force the callbacks to set them up */ + SSL_certs_clear(ssl); +} + +#endif + +static void test_wolfSSL_cert_cb(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_IO_TESTS_DEPENDENCIES) + + callback_functions func_cb_client; + callback_functions func_cb_server; + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); + XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + StartTCP(); + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + server_args.signal = &ready; + client_args.signal = &ready; + client_args.callbacks = &func_cb_client; + server_args.callbacks = &func_cb_server; + func_cb_client.ctx_ready = clientCertSetupCb; + func_cb_client.ssl_ready = clientCertClearCb; + func_cb_server.ctx_ready = serverCertSetupCb; + func_cb_server.ssl_ready = serverCertClearCb; + + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args, NULL); + join_thread(serverThread); + + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + +#endif +} static void test_wolfSSL_SESSION(void) { @@ -37256,16 +37434,25 @@ static void test_wolfSSL_MD5(void) AssertIntEQ(XMEMCMP(&hash, output2, WC_MD5_DIGEST_SIZE), 0); #if !defined(NO_OLD_NAMES) && \ (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))) - AssertIntNE(MD5(NULL, 1, (byte*)&hash), 0); - AssertIntEQ(MD5(input1, 0, (byte*)&hash), 0); - AssertIntNE(MD5(input1, 1, NULL), 0); - AssertIntNE(MD5(NULL, 0, NULL), 0); + AssertPtrNE(MD5(NULL, 1, (byte*)&hash), &hash); + AssertPtrEq(MD5(input1, 0, (byte*)&hash), &hash); + AssertPtrNE(MD5(input1, 1, NULL), NULL); + AssertPtrNE(MD5(NULL, 0, NULL), NULL); - AssertIntEQ(MD5(input1, (int)XSTRLEN((const char*)&input1), (byte*)&hash), 0); + AssertPtrEq(MD5(input1, (int)XSTRLEN((const char*)&input1), (byte*)&hash), &hash); AssertIntEQ(XMEMCMP(&hash, output1, WC_MD5_DIGEST_SIZE), 0); - AssertIntEQ(MD5(input2, (int)XSTRLEN((const char*)&input2), (byte*)&hash), 0); + AssertPtrEq(MD5(input2, (int)XSTRLEN((const char*)&input2), (byte*)&hash), &hash); AssertIntEQ(XMEMCMP(&hash, output2, WC_MD5_DIGEST_SIZE), 0); + { + byte data[] = "Data to be hashed."; + XMEMSET(hash, 0, WC_MD5_DIGEST_SIZE); + + AssertNotNull(MD5(data, sizeof(data), NULL)); + AssertNotNull(MD5(data, sizeof(data), hash)); + AssertNotNull(MD5(NULL, 0, hash)); + AssertNull(MD5(NULL, sizeof(data), hash)); + } #endif printf(resultFmt, passed); @@ -47061,6 +47248,7 @@ void ApiTest(void) test_wolfSSL_CTX_load_verify_locations_ex(); test_wolfSSL_CTX_load_verify_buffer_ex(); test_wolfSSL_CTX_load_verify_chain_buffer_format(); + test_wolfSSL_CTX_add1_chain_cert(); test_wolfSSL_CTX_use_certificate_chain_file_format(); test_wolfSSL_CTX_trust_peer_cert(); test_wolfSSL_CTX_SetTmpDH_file(); @@ -47277,6 +47465,7 @@ void ApiTest(void) test_wolfSSL_BIO_printf(); test_wolfSSL_BIO_f_md(); #endif + test_wolfSSL_cert_cb(); test_wolfSSL_SESSION(); test_wolfSSL_ticket_keys(); test_wolfSSL_DES_ecb_encrypt(); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index acd217bba..f3551e2fd 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -7354,11 +7354,15 @@ int wolfSSL_EVP_PKEY_get_default_digest_nid(WOLFSSL_EVP_PKEY *pkey, int *pnid) int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey) { if (pkey) { +#ifndef SINGLE_THREADED if (wc_LockMutex(&pkey->refMutex) != 0) { WOLFSSL_MSG("Failed to lock pkey mutex"); } +#endif pkey->references++; +#ifndef SINGLE_THREADED wc_UnLockMutex(&pkey->refMutex); +#endif return WOLFSSL_SUCCESS; } @@ -7453,6 +7457,7 @@ WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap) pkey->heap = heap; pkey->type = WOLFSSL_EVP_PKEY_DEFAULT; +#ifndef SINGLE_THREADED /* init of mutex needs to come before wolfSSL_EVP_PKEY_free */ ret = wc_InitMutex(&pkey->refMutex); if (ret != 0){ @@ -7460,6 +7465,7 @@ WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap) WOLFSSL_MSG("Issue initializing mutex"); return NULL; } +#endif #ifndef HAVE_FIPS ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID); @@ -7485,16 +7491,20 @@ void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) int doFree = 0; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_free"); if (key != NULL) { + #ifndef SINGLE_THREADED if (wc_LockMutex(&key->refMutex) != 0) { WOLFSSL_MSG("Couldn't lock pkey mutex"); } + #endif /* only free if all references to it are done */ key->references--; if (key->references == 0) { doFree = 1; } + #ifndef SINGLE_THREADED wc_UnLockMutex(&key->refMutex); + #endif if (doFree) { wc_FreeRng(&key->rng); @@ -7545,9 +7555,11 @@ void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) break; } + #ifndef SINGLE_THREADED if (wc_FreeMutex(&key->refMutex) != 0) { WOLFSSL_MSG("Couldn't free pkey mutex"); } + #endif XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY); } } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 26467fec3..8ec7d8ece 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2107,7 +2107,9 @@ struct WOLFSSL_CERT_MANAGER { /* CTX has ownership and free this */ /* with CTX free. */ #endif +#ifndef SINGLE_THREADED wolfSSL_Mutex refMutex; /* reference count mutex */ +#endif int refCount; /* reference count */ }; @@ -2789,10 +2791,11 @@ struct WOLFSSL_CTX { #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY) WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; #endif - #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ - defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + #ifdef OPENSSL_EXTRA WOLF_STACK_OF(WOLFSSL_X509)* x509Chain; client_cert_cb CBClientCert; /* client certificate callback */ + CertSetupCallback certSetupCb; + void* certSetupCbArg; #endif #ifdef WOLFSSL_TLS13 int certChainCnt; @@ -2952,9 +2955,11 @@ struct WOLFSSL_CTX { pem_password_cb* passwd_cb; void* passwd_userdata; #endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) +#ifdef WOLFSSL_LOCAL_X509_STORE WOLFSSL_X509_STORE x509_store; /* points to ctx->cm */ WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */ +#endif +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) byte readAhead; void* userPRFArg; /* passed to prf callback */ #endif @@ -3355,7 +3360,9 @@ struct WOLFSSL_SESSION { #ifdef OPENSSL_EXTRA byte sessionCtxSz; /* sessionCtx length */ byte sessionCtx[ID_LEN]; /* app specific context id */ +#ifndef SINGLE_THREADED wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif int refCount; /* reference count */ #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) @@ -3881,7 +3888,9 @@ struct WOLFSSL_X509 { int certPoliciesNb; #endif /* WOLFSSL_CERT_EXT */ #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) +#ifndef SINGLE_THREADED wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif int refCount; /* reference count */ #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) @@ -4335,6 +4344,9 @@ struct WOLFSSL { #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) CertReqCtx* certReqCtx; #endif +#ifdef WOLFSSL_LOCAL_X509_STORE + WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */ +#endif #ifdef KEEP_PEER_CERT WOLFSSL_X509 peerCert; /* X509 peer cert */ #endif @@ -4480,6 +4492,9 @@ struct WOLFSSL { #if defined(OPENSSL_EXTRA) WOLFSSL_STACK* supportedCiphers; /* Used in wolfSSL_get_ciphers_compat */ WOLFSSL_STACK* peerCertChain; /* Used in wolfSSL_get_peer_cert_chain */ +#ifdef KEEP_OUR_CERT + WOLFSSL_STACK* ourCertChain; /* Used in wolfSSL_add1_chain_cert */ +#endif #endif #ifdef WOLFSSL_STATIC_EPHEMERAL StaticKeyExchangeInfo_t staticKE; @@ -4495,6 +4510,19 @@ struct WOLFSSL { #endif }; +/* + * The SSL object may have its own certificate store. The below macros simplify + * logic for choosing which WOLFSSL_CERT_MANAGER and WOLFSSL_X509_STORE to use. + * Always use SSL specific objects when available and revert to CTX otherwise. + */ +#ifdef WOLFSSL_LOCAL_X509_STORE +#define SSL_CM(ssl) (ssl->x509_store_pt ? ssl->x509_store_pt->cm : ssl->ctx->cm) +#define SSL_STORE(ssl) (ssl->x509_store_pt ? ssl->x509_store_pt : \ + (ssl->ctx->x509_store_pt ? ssl->ctx->x509_store_pt : \ + &ssl->ctx->x509_store)) +#else +#define SSL_CM(ssl) ssl->ctx->cm +#endif WOLFSSL_LOCAL int SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr); WOLFSSL_LOCAL int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int); diff --git a/wolfssl/openssl/md5.h b/wolfssl/openssl/md5.h index bbbd1ca2f..fe16dae65 100644 --- a/wolfssl/openssl/md5.h +++ b/wolfssl/openssl/md5.h @@ -54,6 +54,8 @@ WOLFSSL_API int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX*, const void*, unsigned long) WOLFSSL_API int wolfSSL_MD5_Final(unsigned char*, WOLFSSL_MD5_CTX*); WOLFSSL_API int wolfSSL_MD5_Transform(WOLFSSL_MD5_CTX*, const unsigned char*); +WOLFSSL_API unsigned char *wolfSSL_MD5(const unsigned char*, size_t, unsigned char*); + typedef WOLFSSL_MD5_CTX MD5_CTX; #define MD5_Init wolfSSL_MD5_Init @@ -67,8 +69,12 @@ typedef WOLFSSL_MD5_CTX MD5_CTX; #define MD5Final wolfSSL_MD5_Final #endif -#ifndef MD5 -#define MD5(d, n, md) wc_Md5Hash((d), (n), (md)) +#if (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2)) && \ + defined(OPENSSL_EXTRA) +/* For fips v1 defined in wolfssl/wolfcrypt/md5.h as + * WC_MD5 for compatibility */ +#define MD5 wolfSSL_MD5 #endif #define MD5_DIGEST_LENGTH MD5_DIGEST_SIZE diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index fb2fc0b81..38bf2be34 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -30,7 +30,7 @@ defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x10100000L) ||\ defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x10001040L) /* valid version */ -#elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) || defined(WOLFSSL_BIND) +#elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) || defined(WOLFSSL_BIND) || defined(WOLFSSL_NGINX) /* For Apache httpd, Use 1.1.0 compatibility */ #define OPENSSL_VERSION_NUMBER 0x10100000L #elif defined(WOLFSSL_QT) diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index 800400115..1c010e4bd 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -84,7 +84,9 @@ typedef struct WOLFSSL_RSA { WOLFSSL_CRYPTO_EX_DATA ex_data; /* external data */ #endif #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) +#ifndef SINGLE_THREADED wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif int refCount; /* reference count */ #endif word16 pkcs8HeaderSz; diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index d5fef61c4..1ede5cbf4 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -301,6 +301,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_CTX_set_verify wolfSSL_CTX_set_verify #define SSL_CTX_set_cert_verify_callback wolfSSL_CTX_set_cert_verify_callback +#define SSL_CTX_set_cert_cb wolfSSL_CTX_set_cert_cb #define SSL_set_verify wolfSSL_set_verify #define SSL_set_verify_result wolfSSL_set_verify_result #define SSL_verify_client_post_handshake wolfSSL_verify_client_post_handshake @@ -824,11 +825,17 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list #define SSL_CTX_set_client_cert_cb wolfSSL_CTX_set_client_cert_cb #define SSL_CTX_set_cert_store wolfSSL_CTX_set_cert_store +#define SSL_set0_verify_cert_store wolfSSL_set0_verify_cert_store +#define SSL_set1_verify_cert_store wolfSSL_set1_verify_cert_store #define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x)) #define SSL_get_client_CA_list wolfSSL_get_client_CA_list #define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx #define SSL_get_ex_data wolfSSL_get_ex_data +#ifndef WOLFSSL_NO_STUB +#define SSL_set_client_CA_list(...) +#endif /* WOLFSSL_NO_STUB */ + #define SSL_CTX_set_default_passwd_cb_userdata wolfSSL_CTX_set_default_passwd_cb_userdata #define SSL_CTX_set_default_passwd_cb wolfSSL_CTX_set_default_passwd_cb @@ -1031,7 +1038,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #endif #define SSL_CTX_use_certificate wolfSSL_CTX_use_certificate +#define SSL_CTX_add0_chain_cert wolfSSL_CTX_add0_chain_cert #define SSL_CTX_add1_chain_cert wolfSSL_CTX_add1_chain_cert +#define SSL_add0_chain_cert wolfSSL_add0_chain_cert +#define SSL_add1_chain_cert wolfSSL_add1_chain_cert #define SSL_CTX_use_PrivateKey wolfSSL_CTX_use_PrivateKey #define BIO_read_filename wolfSSL_BIO_read_filename #define SSL_CTX_set_verify_depth wolfSSL_CTX_set_verify_depth @@ -1109,6 +1119,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_renegotiate_pending wolfSSL_SSL_renegotiate_pending #define SSL_set_tlsext_debug_arg wolfSSL_set_tlsext_debug_arg #define SSL_set_tlsext_status_type wolfSSL_set_tlsext_status_type +#define SSL_get_tlsext_status_type wolfSSL_get_tlsext_status_type #define SSL_set_tlsext_status_exts wolfSSL_set_tlsext_status_exts #define SSL_get_tlsext_status_ids wolfSSL_get_tlsext_status_ids #define SSL_set_tlsext_status_ids wolfSSL_set_tlsext_status_ids @@ -1146,6 +1157,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTRL_SET_SESS_CACHE_MODE 44 #define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE 651 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68 @@ -1274,6 +1286,9 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_add_server_custom_ext(...) 0 +#define SSL_get0_verified_chain wolfSSL_get0_verified_chain +#define X509_chain_up_ref wolfSSL_X509_chain_up_ref + #endif /* HAVE_STUNNEL || WOLFSSL_NGINX */ #ifndef NO_WOLFSSL_STUB @@ -1291,6 +1306,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_clear_extra_chain_certs wolfSSL_CTX_clear_extra_chain_certs +#define SSL_certs_clear wolfSSL_certs_clear /* Nginx uses this to determine if reached end of certs in file. * PEM_read_bio_X509 is called and the return error is lost. @@ -1347,6 +1363,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_R_HTTP_REQUEST PARSE_ERROR #define SSL_R_UNSUPPORTED_PROTOCOL VERSION_ERROR #define SSL_R_CERTIFICATE_VERIFY_FAILED VERIFY_CERT_ERROR +#define SSL_R_CERT_CB_ERROR CLIENT_CERT_CB_ERROR #ifdef HAVE_SESSION_TICKET @@ -1369,6 +1386,8 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_set_tlsext_ticket_key_cb wolfSSL_CTX_set_tlsext_ticket_key_cb #define SSL_CTX_set_tlsext_status_cb wolfSSL_CTX_set_tlsext_status_cb #define SSL_CTX_get_extra_chain_certs wolfSSL_CTX_get_extra_chain_certs +#define SSL_CTX_get0_chain_certs wolfSSL_CTX_get0_chain_certs +#define SSL_get0_chain_certs wolfSSL_get0_chain_certs #define sk_OPENSSL_STRING_num wolfSSL_sk_WOLFSSL_STRING_num #define sk_OPENSSL_STRING_value wolfSSL_sk_WOLFSSL_STRING_value #define sk_OPENSSL_PSTRING_num wolfSSL_sk_WOLFSSL_STRING_num diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 29b97ea4e..b90386597 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -104,6 +104,13 @@ extern "C" { #endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) +#ifndef WOLFSSL_LOCAL_X509_STORE +#define WOLFSSL_LOCAL_X509_STORE +#endif +#endif + /* LHASH is implemented as a stack */ typedef struct WOLFSSL_STACK WOLFSSL_LHASH; #ifndef WOLF_LHASH_OF @@ -354,7 +361,9 @@ struct WOLFSSL_EVP_PKEY { int save_type; /* openssh dereference */ int pkey_sz; int references; /*number of times free should be called for complete free*/ +#ifndef SINGLE_THREADED wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif union { char* ptr; /* der format of key / or raw for NTRU */ @@ -552,7 +561,7 @@ struct WOLFSSL_X509_STORE { int cache; /* stunnel dereference */ WOLFSSL_CERT_MANAGER* cm; WOLFSSL_X509_LOOKUP lookup; -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) int isDynamic; WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */ #endif @@ -565,9 +574,13 @@ struct WOLFSSL_X509_STORE { #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; #endif -#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && defined(HAVE_CRL) +#ifdef HAVE_CRL WOLFSSL_X509_CRL *crl; /* points to cm->crl */ #endif +#ifndef SINGLE_THREADED + wolfSSL_Mutex refMutex; /* reference count mutex */ +#endif + int refCount; /* reference count */ }; #define WOLFSSL_NO_WILDCARDS 0x4 @@ -710,6 +723,7 @@ enum AlertDescription { #else protocol_version = 70, #endif + internal_error = 80, inappropriate_fallback = 86, no_renegotiation = 100, missing_extension = 109, @@ -1672,6 +1686,7 @@ WOLFSSL_API WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STOR WOLFSSL_X509_LOOKUP_METHOD*); WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void); WOLFSSL_API void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE*); +WOLFSSL_API int wolfSSL_X509_STORE_up_ref(WOLFSSL_X509_STORE*); WOLFSSL_API int wolfSSL_X509_STORE_add_cert( WOLFSSL_X509_STORE*, WOLFSSL_X509*); WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain( @@ -1798,6 +1813,11 @@ typedef int (*client_cert_cb)(WOLFSSL *ssl, WOLFSSL_X509 **x509, WOLFSSL_EVP_PKEY **pkey); WOLFSSL_API void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb); +typedef int (*CertSetupCallback)(WOLFSSL*, void*); +WOLFSSL_API void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx, + CertSetupCallback cb, void *arg); +WOLFSSL_LOCAL int CertSetupCbWrapper(WOLFSSL* ssl); + WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data( WOLFSSL_X509_STORE_CTX* ctx, int idx); WOLFSSL_API int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, @@ -1905,6 +1925,7 @@ WOLFSSL_API int wolfSSL_SSL_renegotiate_pending(WOLFSSL *s); WOLFSSL_API long wolfSSL_set_tmp_dh(WOLFSSL *s, WOLFSSL_DH *dh); WOLFSSL_API long wolfSSL_set_tlsext_debug_arg(WOLFSSL *s, void *arg); WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type); +WOLFSSL_API long wolfSSL_get_tlsext_status_type(WOLFSSL *s); WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg); WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg); WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg); @@ -3721,6 +3742,8 @@ WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt); WOLFSSL_API long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void)); WOLFSSL_API long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx); +WOLFSSL_API void wolfSSL_certs_clear(WOLFSSL* ssl); + #ifndef NO_CERTS WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID( WOLFSSL_X509_NAME_ENTRY** out, int nid, int type, @@ -3825,8 +3848,8 @@ WOLFSSL_API int wolfSSL_i2d_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); #if !defined(NO_FILESYSTEM) WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509** x509); -WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s); #endif +WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s); WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509); #ifdef WOLFSSL_CERT_REQ @@ -3836,8 +3859,14 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_REQ_bio(WOLFSSL_BIO* bio, #endif /* OPENSSL_EXTRA || OPENSSL_ALL */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain( + const WOLFSSL *ssl); WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str); +WOLFSSL_API int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, + WOLFSSL_X509_STORE* str); +WOLFSSL_API int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, + WOLFSSL_X509_STORE* str); WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx); #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ @@ -3920,7 +3949,10 @@ WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne); WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void); WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name); WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_CTX_add0_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*); WOLFSSL_API int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_add0_chain_cert(WOLFSSL*, WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_add1_chain_cert(WOLFSSL*, WOLFSSL_X509*); WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); /* These are to be merged shortly */ WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth); @@ -4371,6 +4403,11 @@ typedef int(*tlsextStatusCb)(WOLFSSL*, void*); WOLFSSL_API int wolfSSL_CTX_get_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb* cb); WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb); +WOLFSSL_API int wolfSSL_CTX_get0_chain_certs(WOLFSSL_CTX *ctx, + WOLF_STACK_OF(WOLFSSL_X509) **sk); +WOLFSSL_API int wolfSSL_get0_chain_certs(WOLFSSL *ssl, + WOLF_STACK_OF(WOLFSSL_X509) **sk); + WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x); diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index d469147bc..4d9f881f4 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -42,7 +42,7 @@ extern "C" { #endif -#if !defined(NO_OLD_MD5_NAME) +#ifndef NO_OLD_MD5_NAME #define MD5 WC_MD5 #endif