Fix to handle non-blocking OCSP when WOLFSSL_NONBLOCK_OCSP is defined and not using async. OCSP callback should return OCSP_WANT_READ. Added ability to simulate non-blocking OCSP using TEST_NONBLOCK_CERTS.

This commit is contained in:
David Garske
2017-12-08 03:12:33 +01:00
parent 24ef88f6f0
commit de05c563b6
6 changed files with 101 additions and 34 deletions

View File

@ -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

View File

@ -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";

View File

@ -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);

View File

@ -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 */

View File

@ -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) */

View File

@ -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))