diff --git a/examples/client/client.c b/examples/client/client.c index 4dbd6da1a..e080f77b5 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1582,8 +1582,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE | WOLFSSL_OCSP_URL_OVERRIDE); } - else + else { wolfSSL_CTX_EnableOCSP(ctx, 0); + } + + #ifdef WOLFSSL_NONBLOCK_OCSP + wolfSSL_CTX_SetOCSP_Cb(ctx, OCSPIOCb, OCSPRespFreeCb, NULL); + #endif } #endif diff --git a/src/internal.c b/src/internal.c index a6989c419..478c1f1de 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7752,6 +7752,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args; typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; (void)sizeof(args_test); +#elif defined(WOLFSSL_NONBLOCK_OCSP) + ProcPeerCertArgs* args = ssl->nonblockarg; #else ProcPeerCertArgs args[1]; #endif @@ -7771,6 +7773,15 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, goto exit_ppc; } else +#elif defined(WOLFSSL_NONBLOCK_OCSP) + if (args == NULL) { + args = (ProcPeerCertArgs*)XMALLOC( + sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + } + if (ssl->nonblockarg == NULL) /* new args */ #endif { /* Reset state */ @@ -7781,6 +7792,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args->begin = *inOutIdx; #ifdef WOLFSSL_ASYNC_CRYPT ssl->async.freeArgs = FreeProcPeerCertArgs; + #elif defined(WOLFSSL_NONBLOCK_OCSP) + ssl->nonblockarg = args; #endif } @@ -8229,9 +8242,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("Doing Non Leaf OCSP check"); ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp, args->dCert, NULL, ssl); - #ifdef WOLFSSL_ASYNC_CRYPT - /* non-blocking socket re-entry requires async */ - if (ret == WANT_READ) { + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { goto exit_ppc; } #endif @@ -8249,9 +8261,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ssl->ctx->cm->crlCheckAll) { WOLFSSL_MSG("Doing Non Leaf CRL check"); ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); - #ifdef WOLFSSL_ASYNC_CRYPT - /* non-blocking socket re-entry requires async */ - if (ret == WANT_READ) { + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { goto exit_ppc; } #endif @@ -8379,7 +8390,21 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } } #endif /* HAVE_SECURE_RENEGOTIATION */ + } /* if (count > 0) */ + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + if (args->count > 0) { #if defined(HAVE_OCSP) || defined(HAVE_CRL) if (args->fatal == 0) { int doLookup = 1; @@ -8406,9 +8431,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("Doing Leaf OCSP check"); ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp, args->dCert, NULL, ssl); - #ifdef WOLFSSL_ASYNC_CRYPT - /* non-blocking socket re-entry requires async */ - if (ret == WANT_READ) { + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { goto exit_ppc; } #endif @@ -8427,9 +8451,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (doLookup && ssl->ctx->cm->crlEnabled) { WOLFSSL_MSG("Doing Leaf CRL check"); ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); - #ifdef WOLFSSL_ASYNC_CRYPT - /* non-blocking socket re-entry requires async */ - if (ret == WANT_READ) { + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { goto exit_ppc; } #endif @@ -8499,21 +8522,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } ssl->options.havePeerCert = 1; - } /* if (count > 0) */ - /* Check for error */ - if (args->fatal && ret != 0) { - goto exit_ppc; - } - - /* Advance state and proceed */ - ssl->options.asyncState = TLS_ASYNC_VERIFY; - } /* case TLS_ASYNC_DO */ - FALL_THROUGH; - - case TLS_ASYNC_VERIFY: - { - if (args->count > 0) { args->domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap, DYNAMIC_TYPE_STRING); if (args->domain == NULL) { @@ -8898,16 +8907,23 @@ exit_ppc: WOLFSSL_LEAVE("ProcessPeerCerts", ret); -#ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E || ret == WANT_READ) { + +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) { /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_certificate = 0; return ret; } -#endif /* WOLFSSL_ASYNC_CRYPT */ +#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */ FreeProcPeerCertArgs(ssl, args); + +#if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_NONBLOCK_OCSP) + XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->nonblockarg = NULL; +#endif + FreeKeyExchange(ssl); return ret; @@ -9703,9 +9719,9 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DECODE_E; } -#ifdef WOLFSSL_ASYNC_CRYPT +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) /* if async, offset index so this msg will be processed again */ - if (ret == WC_PENDING_E && *inOutIdx > 0) { + if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) { *inOutIdx -= HANDSHAKE_HEADER_SZ; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -9713,7 +9729,12 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif } +#ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + ret = WANT_READ; /* treat as normal WANT_READ for non-block handling */ + } #endif +#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */ WOLFSSL_LEAVE("DoHandShakeMsgType()", ret); return ret; @@ -14451,6 +14472,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case OCSP_INVALID_STATUS: return "Invalid OCSP Status Error"; + case OCSP_WANT_READ: + return "OCSP nonblock wants read"; + case RSA_KEY_SIZE_E: return "RSA key too small"; diff --git a/src/ocsp.c b/src/ocsp.c index 399eb0a23..727bfbedd 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -459,7 +459,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, request, requestSz, &response); } if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) { - ret = WANT_READ; + ret = OCSP_WANT_READ; } XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index facab69a9..3ab6d3cdf 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -142,7 +142,7 @@ enum wolfSSL_ErrorCodes { UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/ BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */ OCSP_INVALID_STATUS = -407, /* Invalid OCSP Status */ - + OCSP_WANT_READ = -408, /* OCSP callback response WOLFSSL_CBIO_ERR_WANT_READ */ RSA_KEY_SIZE_E = -409, /* RSA key too small */ ECC_KEY_SIZE_E = -410, /* ECC key too small */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9c77120a1..89b5e550c 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3282,6 +3282,8 @@ struct WOLFSSL { #endif #ifdef WOLFSSL_ASYNC_CRYPT struct WOLFSSL_ASYNC async; +#elif defined(WOLFSSL_NONBLOCK_OCSP) + void* nonblockarg; /* dynamic arg for handling non-block resume */ #endif void* hsKey; /* Handshake key (RsaKey or ecc_key) allocated from heap */ word32 hsType; /* Type of Handshake key (hsKey) */ diff --git a/wolfssl/test.h b/wolfssl/test.h index cad7e38bc..e86d79db5 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1128,6 +1128,42 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, #endif /* USE_WINDOWS_API */ +#if defined(HAVE_OCSP) && defined(WOLFSSL_NONBLOCK_OCSP) +static INLINE int OCSPIOCb(void* ioCtx, const char* url, int urlSz, + unsigned char* request, int requestSz, unsigned char** response) +{ +#ifdef TEST_NONBLOCK_CERTS + static int ioCbCnt = 0; +#endif + + (void)ioCtx; + (void)url; + (void)urlSz; + (void)request; + (void)requestSz; + (void)response; + +#ifdef TEST_NONBLOCK_CERTS + if (ioCbCnt) { + ioCbCnt = 0; + return EmbedOcspLookup(ioCtx, url, urlSz, request, requestSz, response); + } + else { + ioCbCnt = 1; + return WOLFSSL_CBIO_ERR_WANT_READ; + } +#else + return EmbedOcspLookup(ioCtx, url, urlSz, request, requestSz, response); +#endif +} + +static INLINE void OCSPRespFreeCb(void* ioCtx, unsigned char* response) +{ + (void)ioCtx; + (void)response; +} +#endif + #if !defined(NO_CERTS) #if !defined(NO_FILESYSTEM) || \ (defined(NO_FILESYSTEM) && defined(FORCE_BUFFER_TEST))