add wolfSSL_write_dup(), creates write_only WOLFSSL to allow concurrent access
This commit is contained in:
parent
52215b3ecf
commit
15423428ed
14
configure.ac
14
configure.ac
@ -476,6 +476,19 @@ then
|
||||
fi
|
||||
|
||||
|
||||
# Write duplicate WOLFSSL object
|
||||
AC_ARG_ENABLE([writedup],
|
||||
[ --enable-writedup Enable write duplication of WOLFSSL objects (default: disabled)],
|
||||
[ ENABLED_WRITEDUP=$enableval ],
|
||||
[ ENABLED_WRITEDUP=no ]
|
||||
)
|
||||
|
||||
if test "$ENABLED_WRITEDUP" = "yes"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_WRITE_DUP"
|
||||
fi
|
||||
|
||||
|
||||
# Atomic User Record Layer
|
||||
AC_ARG_ENABLE([atomicuser],
|
||||
[ --enable-atomicuser Enable Atomic User Record Layer (default: disabled)],
|
||||
@ -3480,6 +3493,7 @@ echo " * Async Crypto: $ENABLED_ASYNCCRYPT"
|
||||
echo " * Cavium: $ENABLED_CAVIUM"
|
||||
echo " * ARM ASM: $ENABLED_ARMASM"
|
||||
echo " * AES Key Wrap: $ENABLED_AESKEYWRAP"
|
||||
echo " * Write duplicate: $ENABLED_WRITEDUP"
|
||||
echo ""
|
||||
echo "---"
|
||||
|
||||
|
@ -241,7 +241,8 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
|
||||
SignalReady(args, port);
|
||||
|
||||
while (!shutDown) {
|
||||
CYASSL* ssl = 0;
|
||||
CYASSL* ssl = NULL;
|
||||
CYASSL* write_ssl = NULL; /* may have separate w/ HAVE_WRITE_DUP */
|
||||
char command[SVR_COMMAND_SIZE+1];
|
||||
int echoSz = 0;
|
||||
int clientfd;
|
||||
@ -308,6 +309,18 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
|
||||
showPeer(ssl);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
write_ssl = wolfSSL_write_dup(ssl);
|
||||
if (write_ssl == NULL) {
|
||||
printf("wolfSSL_write_dup failed\n");
|
||||
CyaSSL_free(ssl);
|
||||
CloseSocket(clientfd);
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
write_ssl = ssl;
|
||||
#endif
|
||||
|
||||
while ( (echoSz = CyaSSL_read(ssl, command, sizeof(command)-1)) > 0) {
|
||||
|
||||
if (firstRead == 1) {
|
||||
@ -354,7 +367,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
|
||||
strncpy(&command[echoSz], footer, sizeof(footer));
|
||||
echoSz += (int)sizeof(footer);
|
||||
|
||||
if (CyaSSL_write(ssl, command, echoSz) != echoSz)
|
||||
if (CyaSSL_write(write_ssl, command, echoSz) != echoSz)
|
||||
err_sys("SSL_write failed");
|
||||
break;
|
||||
}
|
||||
@ -364,11 +377,14 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
|
||||
fputs(command, fout);
|
||||
#endif
|
||||
|
||||
if (CyaSSL_write(ssl, command, echoSz) != echoSz)
|
||||
if (CyaSSL_write(write_ssl, command, echoSz) != echoSz)
|
||||
err_sys("SSL_write failed");
|
||||
}
|
||||
#ifndef CYASSL_DTLS
|
||||
CyaSSL_shutdown(ssl);
|
||||
#endif
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
CyaSSL_free(write_ssl);
|
||||
#endif
|
||||
CyaSSL_free(ssl);
|
||||
CloseSocket(clientfd);
|
||||
|
190
src/internal.c
190
src/internal.c
@ -3187,8 +3187,14 @@ int DhAgree(WOLFSSL* ssl,
|
||||
/* This function inherits a WOLFSSL_CTX's fields into an SSL object.
|
||||
It is used during initialization and to switch an ssl's CTX with
|
||||
wolfSSL_Set_SSL_CTX. Requires ssl->suites alloc and ssl-arrays with PSK
|
||||
unless writeDup is on.
|
||||
|
||||
ssl object to initialize
|
||||
ctx parent factory
|
||||
writeDup flag indicating this is a write dup only
|
||||
|
||||
SSL_SUCCESS return value on success */
|
||||
int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||
{
|
||||
byte havePSK = 0;
|
||||
byte haveAnon = 0;
|
||||
@ -3196,13 +3202,16 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
byte haveRSA = 0;
|
||||
(void) haveAnon; /* Squash unused var warnings */
|
||||
|
||||
if(!ssl || !ctx || ssl->suites == NULL)
|
||||
if (!ssl || !ctx)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (ssl->suites == NULL && !writeDup)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
newSSL = ssl->ctx == NULL; /* Assign after null check */
|
||||
|
||||
#ifndef NO_PSK
|
||||
if (ctx->server_hint[0] && ssl->arrays == NULL) {
|
||||
if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) {
|
||||
return BAD_FUNC_ARG; /* needed for copy below */
|
||||
}
|
||||
#endif
|
||||
@ -3307,41 +3316,45 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
ssl->devId = ctx->devId;
|
||||
#endif
|
||||
|
||||
if (writeDup == 0) {
|
||||
|
||||
#ifndef NO_PSK
|
||||
if (ctx->server_hint[0]) { /* set in CTX */
|
||||
XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, MAX_PSK_ID_LEN);
|
||||
ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0';
|
||||
}
|
||||
if (ctx->server_hint[0]) { /* set in CTX */
|
||||
XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint,MAX_PSK_ID_LEN);
|
||||
ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0';
|
||||
}
|
||||
#endif /* NO_PSK */
|
||||
|
||||
if (ctx->suites)
|
||||
*ssl->suites = *ctx->suites;
|
||||
else
|
||||
XMEMSET(ssl->suites, 0, sizeof(Suites));
|
||||
if (ctx->suites)
|
||||
*ssl->suites = *ctx->suites;
|
||||
else
|
||||
XMEMSET(ssl->suites, 0, sizeof(Suites));
|
||||
|
||||
/* make sure server has DH parms, and add PSK if there, add NTRU too */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END)
|
||||
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
|
||||
/* make sure server has DH parms, and add PSK if there, add NTRU too */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END)
|
||||
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
|
||||
ssl->options.haveDH, ssl->options.haveNTRU,
|
||||
ssl->options.haveECDSAsig, ssl->options.haveECC,
|
||||
ssl->options.haveStaticECC, ssl->options.side);
|
||||
else
|
||||
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE,
|
||||
else
|
||||
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE,
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSAsig,
|
||||
ssl->options.haveECC, ssl->options.haveStaticECC,
|
||||
ssl->options.side);
|
||||
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
|
||||
/* make sure server has cert and key unless using PSK or Anon
|
||||
* This should be true even if just switching ssl ctx */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
|
||||
if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer ||
|
||||
!ssl->buffers.key || !ssl->buffers.key->buffer) {
|
||||
WOLFSSL_MSG("Server missing certificate and/or private key");
|
||||
return NO_PRIVATE_KEY;
|
||||
}
|
||||
/* make sure server has cert and key unless using PSK or Anon
|
||||
* This should be true even if just switching ssl ctx */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
|
||||
if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer
|
||||
|| !ssl->buffers.key || !ssl->buffers.key->buffer) {
|
||||
WOLFSSL_MSG("Server missing certificate and/or private key");
|
||||
return NO_PRIVATE_KEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* writeDup check */
|
||||
|
||||
#ifdef WOLFSSL_SESSION_EXPORT
|
||||
#ifdef WOLFSSL_DTLS
|
||||
ssl->dtls_export = ctx->dtls_export; /* export function for session */
|
||||
@ -3358,8 +3371,13 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
|
||||
/* init everything to 0, NULL, default values before calling anything that may
|
||||
fail so that destructor has a "good" state to cleanup
|
||||
|
||||
ssl object to initialize
|
||||
ctx parent factory
|
||||
writeDup flag indicating this is a write dup only
|
||||
|
||||
0 on success */
|
||||
int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -3542,30 +3560,65 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
|
||||
/* all done with init, now can return errors, call other stuff */
|
||||
|
||||
/* arrays */
|
||||
ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
|
||||
if (!writeDup) {
|
||||
/* arrays */
|
||||
ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
|
||||
DYNAMIC_TYPE_ARRAYS);
|
||||
if (ssl->arrays == NULL) {
|
||||
WOLFSSL_MSG("Arrays Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->arrays, 0, sizeof(Arrays));
|
||||
if (ssl->arrays == NULL) {
|
||||
WOLFSSL_MSG("Arrays Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->arrays, 0, sizeof(Arrays));
|
||||
|
||||
/* suites */
|
||||
ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
|
||||
/* suites */
|
||||
ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
|
||||
DYNAMIC_TYPE_SUITES);
|
||||
if (ssl->suites == NULL) {
|
||||
WOLFSSL_MSG("Suites Memory error");
|
||||
return MEMORY_E;
|
||||
if (ssl->suites == NULL) {
|
||||
WOLFSSL_MSG("Suites Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize SSL with the appropriate fields from it's ctx */
|
||||
/* requires valid arrays and suites */
|
||||
if((ret = SetSSL_CTX(ssl, ctx)) != SSL_SUCCESS)
|
||||
/* requires valid arrays and suites unless writeDup ing */
|
||||
if ((ret = SetSSL_CTX(ssl, ctx, writeDup)) != SSL_SUCCESS)
|
||||
return ret;
|
||||
|
||||
ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
|
||||
|
||||
#ifdef SINGLE_THREADED
|
||||
ssl->rng = ctx->rng; /* CTX may have one, if so use it */
|
||||
#endif
|
||||
|
||||
if (ssl->rng == NULL) {
|
||||
/* RNG */
|
||||
ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG);
|
||||
if (ssl->rng == NULL) {
|
||||
WOLFSSL_MSG("RNG Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->rng, 0, sizeof(WC_RNG));
|
||||
ssl->options.weOwnRng = 1;
|
||||
|
||||
/* FIPS RNG API does not accept a heap hint */
|
||||
#ifndef HAVE_FIPS
|
||||
if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) {
|
||||
WOLFSSL_MSG("RNG Init error");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
if ( (ret = wc_InitRng(ssl->rng)) != 0) {
|
||||
WOLFSSL_MSG("RNG Init error");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (writeDup) {
|
||||
/* all done */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hsHashes */
|
||||
ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap,
|
||||
DYNAMIC_TYPE_HASHES);
|
||||
@ -3604,34 +3657,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SINGLE_THREADED
|
||||
ssl->rng = ctx->rng; /* CTX may have one, if so use it */
|
||||
#endif
|
||||
|
||||
if (ssl->rng == NULL) {
|
||||
/* RNG */
|
||||
ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG);
|
||||
if (ssl->rng == NULL) {
|
||||
WOLFSSL_MSG("RNG Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->rng, 0, sizeof(WC_RNG));
|
||||
ssl->options.weOwnRng = 1;
|
||||
|
||||
/* FIPS RNG API does not accept a heap hint */
|
||||
#ifndef HAVE_FIPS
|
||||
if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) {
|
||||
WOLFSSL_MSG("RNG Init error");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
if ( (ret = wc_InitRng(ssl->rng)) != 0) {
|
||||
WOLFSSL_MSG("RNG Init error");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
|
||||
if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
|
||||
@ -3842,6 +3867,11 @@ void SSL_ResourceFree(WOLFSSL* ssl)
|
||||
#ifdef HAVE_EXT_CACHE
|
||||
wolfSSL_SESSION_free(ssl->extSession);
|
||||
#endif
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
if (ssl->dupWrite) {
|
||||
FreeWriteDup(ssl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_STATIC_MEMORY
|
||||
/* check if using fixed io buffers and free them */
|
||||
@ -11588,6 +11618,26 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
|
||||
int outputSz;
|
||||
int dtlsExtra = 0;
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
|
||||
int notifyErr = 0;
|
||||
|
||||
WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling");
|
||||
|
||||
if (type == close_notify) {
|
||||
notifyErr = ZERO_RETURN;
|
||||
} else if (severity == alert_fatal) {
|
||||
notifyErr = FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (notifyErr != 0) {
|
||||
return NotifyWriteSide(ssl, notifyErr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if sendalert is called again for nonblocking */
|
||||
if (ssl->options.sendAlertState != 0) {
|
||||
ret = SendBuffered(ssl);
|
||||
@ -12024,6 +12074,12 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
|
||||
case DECODE_E:
|
||||
return "Decode handshake message error";
|
||||
|
||||
case WRITE_DUP_READ_E:
|
||||
return "Write dup write side can't read error";
|
||||
|
||||
case WRITE_DUP_WRITE_E:
|
||||
return "Write dup read side can't write error";
|
||||
|
||||
default :
|
||||
return "unknown error number";
|
||||
}
|
||||
|
212
src/ssl.c
212
src/ssl.c
@ -372,7 +372,7 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
|
||||
|
||||
ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL);
|
||||
if (ssl)
|
||||
if ( (ret = InitSSL(ssl, ctx)) < 0) {
|
||||
if ( (ret = InitSSL(ssl, ctx, 0)) < 0) {
|
||||
FreeSSL(ssl, ctx->heap);
|
||||
ssl = 0;
|
||||
}
|
||||
@ -390,6 +390,162 @@ void wolfSSL_free(WOLFSSL* ssl)
|
||||
WOLFSSL_LEAVE("SSL_free", 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
|
||||
/*
|
||||
* Release resources around WriteDup object
|
||||
*
|
||||
* ssl WOLFSSL object
|
||||
*
|
||||
* no return, destruction so make best attempt
|
||||
*/
|
||||
void FreeWriteDup(WOLFSSL* ssl)
|
||||
{
|
||||
int doFree = 0;
|
||||
|
||||
WOLFSSL_ENTER("FreeWriteDup");
|
||||
|
||||
if (ssl->dupWrite) {
|
||||
if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
|
||||
ssl->dupWrite->dupCount--;
|
||||
if (ssl->dupWrite->dupCount == 0) {
|
||||
doFree = 1;
|
||||
} else {
|
||||
WOLFSSL_MSG("WriteDup count not zero, no full free");
|
||||
}
|
||||
wc_UnLockMutex(&ssl->dupWrite->dupMutex);
|
||||
}
|
||||
}
|
||||
|
||||
if (doFree) {
|
||||
WOLFSSL_MSG("Doing WriteDup full free, count to zero");
|
||||
wc_FreeMutex(&ssl->dupWrite->dupMutex);
|
||||
XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* duplicate existing ssl members into dup needed for writing
|
||||
*
|
||||
* dup write only WOLFSSL
|
||||
* ssl exisiting WOLFSSL
|
||||
*
|
||||
* 0 on success
|
||||
*/
|
||||
static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl)
|
||||
{
|
||||
/* shared dupWrite setup */
|
||||
ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap,
|
||||
DYNAMIC_TYPE_WRITEDUP);
|
||||
if (ssl->dupWrite == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup));
|
||||
|
||||
if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) {
|
||||
XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
|
||||
ssl->dupWrite = NULL;
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
ssl->dupWrite->dupCount = 2; /* both sides have a count to start */
|
||||
dup->dupWrite = ssl->dupWrite ; /* each side uses */
|
||||
|
||||
/* copy write parts over to dup writer */
|
||||
XMEMCPY(&dup->specs, &ssl->specs, sizeof(CipherSpecs));
|
||||
XMEMCPY(&dup->options, &ssl->options, sizeof(Options));
|
||||
XMEMCPY(&dup->keys, &ssl->keys, sizeof(Keys));
|
||||
XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers));
|
||||
/* dup side now owns encrypt/write ciphers */
|
||||
XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers));
|
||||
|
||||
dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx;
|
||||
dup->wfd = ssl->wfd;
|
||||
dup->wflags = ssl->wflags;
|
||||
dup->hmac = ssl->hmac;
|
||||
#ifdef HAVE_TRUNCATED_HMAC
|
||||
dup->truncated_hmac = ssl->truncated_hmac;
|
||||
#endif
|
||||
|
||||
/* unique side dup setup */
|
||||
dup->dupSide = WRITE_DUP_SIDE;
|
||||
ssl->dupSide = READ_DUP_SIDE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* duplicate a WOLFSSL object post handshake for writing only
|
||||
* turn exisitng object into read only. Allows concurrent access from two
|
||||
* different threads.
|
||||
*
|
||||
* ssl exisiting WOLFSSL object
|
||||
*
|
||||
* return dup'd WOLFSSL object on success
|
||||
*/
|
||||
WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl)
|
||||
{
|
||||
WOLFSSL* dup = NULL;
|
||||
int ret = 0;
|
||||
|
||||
(void)ret;
|
||||
WOLFSSL_ENTER("wolfSSL_write_dup");
|
||||
|
||||
if (ssl == NULL) {
|
||||
return ssl;
|
||||
}
|
||||
|
||||
if (ssl->options.handShakeDone == 0) {
|
||||
WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL);
|
||||
if (dup) {
|
||||
if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) {
|
||||
FreeSSL(dup, ssl->ctx->heap);
|
||||
dup = NULL;
|
||||
} else if ( (ret = DupSSL(dup, ssl) < 0)) {
|
||||
FreeSSL(dup, ssl->ctx->heap);
|
||||
dup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_write_dup", ret);
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Notify write dup side of fatal error or close notify
|
||||
*
|
||||
* ssl WOLFSSL object
|
||||
* err Notify err
|
||||
*
|
||||
* 0 on success
|
||||
*/
|
||||
int NotifyWriteSide(WOLFSSL* ssl, int err)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WOLFSSL_ENTER("NotifyWriteSide");
|
||||
|
||||
ret = wc_LockMutex(&ssl->dupWrite->dupMutex);
|
||||
if (ret == 0) {
|
||||
ssl->dupWrite->dupErr = err;
|
||||
ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_WRITE_DUP */
|
||||
|
||||
|
||||
#ifdef HAVE_POLY1305
|
||||
/* set if to use old poly 1 for yes 0 to use new poly */
|
||||
int wolfSSL_use_old_poly(WOLFSSL* ssl, int value)
|
||||
@ -1114,6 +1270,36 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
|
||||
if (ssl == NULL || data == NULL || sz < 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
{ /* local variable scope */
|
||||
int dupErr = 0; /* local copy */
|
||||
|
||||
ret = 0;
|
||||
|
||||
if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
|
||||
WOLFSSL_MSG("Read dup side cannot write");
|
||||
return WRITE_DUP_WRITE_E;
|
||||
}
|
||||
if (ssl->dupWrite) {
|
||||
if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) {
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
dupErr = ssl->dupWrite->dupErr;
|
||||
ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
ssl->error = ret; /* high priority fatal error */
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
if (dupErr != 0) {
|
||||
WOLFSSL_MSG("Write dup error from other side");
|
||||
ssl->error = dupErr;
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
errno = 0;
|
||||
#endif
|
||||
@ -1138,6 +1324,13 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
|
||||
if (ssl == NULL || data == NULL || sz < 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
|
||||
WOLFSSL_MSG("Write dup side cannot read");
|
||||
return WRITE_DUP_READ_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
errno = 0;
|
||||
#endif
|
||||
@ -1158,6 +1351,21 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
|
||||
#endif
|
||||
ret = ReceiveData(ssl, (byte*)data, sz, peek);
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
if (ssl->dupWrite) {
|
||||
if (ssl->error != 0 && ssl->error != WANT_READ &&
|
||||
ssl->error != WC_PENDING_E) {
|
||||
int notifyErr;
|
||||
|
||||
WOLFSSL_MSG("Notifying write side of fatal read error");
|
||||
notifyErr = NotifyWriteSide(ssl, ssl->error);
|
||||
if (notifyErr < 0) {
|
||||
ret = ssl->error = notifyErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_read_internal()", ret);
|
||||
|
||||
if (ret < 0)
|
||||
@ -22603,7 +22811,7 @@ const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
|
||||
|
||||
WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
{
|
||||
if (ssl && ctx && SetSSL_CTX(ssl, ctx) == SSL_SUCCESS)
|
||||
if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == SSL_SUCCESS)
|
||||
return ssl->ctx;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -153,6 +153,8 @@ enum wolfSSL_ErrorCodes {
|
||||
DTLS_POOL_SZ_E = -415, /* exceeded DTLS pool size */
|
||||
DECODE_E = -416, /* decode handshake message error */
|
||||
HTTP_TIMEOUT = -417, /* HTTP timeout for OCSP or CRL req */
|
||||
WRITE_DUP_READ_E = -418, /* Write dup write side can't read */
|
||||
WRITE_DUP_WRITE_E = -419, /* Write dup read side can't write */
|
||||
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
|
||||
|
||||
/* begin negotiation parameter errors */
|
||||
|
@ -2754,6 +2754,22 @@ typedef struct HS_Hashes {
|
||||
} HS_Hashes;
|
||||
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
|
||||
#define WRITE_DUP_SIDE 1
|
||||
#define READ_DUP_SIDE 2
|
||||
|
||||
typedef struct WriteDup {
|
||||
wolfSSL_Mutex dupMutex; /* reference count mutex */
|
||||
int dupCount; /* reference count */
|
||||
int dupErr; /* under dupMutex, pass to other side */
|
||||
} WriteDup;
|
||||
|
||||
WOLFSSL_LOCAL void FreeWriteDup(WOLFSSL* ssl);
|
||||
WOLFSSL_LOCAL int NotifyWriteSide(WOLFSSL* ssl, int err);
|
||||
#endif /* HAVE_WRITE_DUP */
|
||||
|
||||
|
||||
/* wolfSSL ssl type */
|
||||
struct WOLFSSL {
|
||||
WOLFSSL_CTX* ctx;
|
||||
@ -2766,6 +2782,11 @@ struct WOLFSSL {
|
||||
void* verifyCbCtx; /* cert verify callback user ctx*/
|
||||
VerifyCallback verifyCallback; /* cert verification callback */
|
||||
void* heap; /* for user overrides */
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
WriteDup* dupWrite; /* valid pointer indicates ON */
|
||||
/* side that decrements dupCount to zero frees overall structure */
|
||||
byte dupSide; /* write side or read side */
|
||||
#endif
|
||||
#ifdef WOLFSSL_STATIC_MEMORY
|
||||
WOLFSSL_HEAP_HINT heap_hint;
|
||||
#endif
|
||||
@ -2967,9 +2988,9 @@ struct WOLFSSL {
|
||||
|
||||
|
||||
WOLFSSL_LOCAL
|
||||
int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*);
|
||||
int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int);
|
||||
WOLFSSL_LOCAL
|
||||
int InitSSL(WOLFSSL*, WOLFSSL_CTX*);
|
||||
int InitSSL(WOLFSSL*, WOLFSSL_CTX*, int);
|
||||
WOLFSSL_LOCAL
|
||||
void FreeSSL(WOLFSSL*, void* heap);
|
||||
WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */
|
||||
|
@ -369,6 +369,7 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int);
|
||||
|
||||
WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*);
|
||||
WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*);
|
||||
WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*);
|
||||
WOLFSSL_API int wolfSSL_set_fd (WOLFSSL*, int);
|
||||
WOLFSSL_API int wolfSSL_set_write_fd (WOLFSSL*, int);
|
||||
WOLFSSL_API int wolfSSL_set_read_fd (WOLFSSL*, int);
|
||||
|
@ -1230,6 +1230,12 @@ static char *fgets(char *buff, int sz, FILE *fp)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* write dup cannot be used with secure renegotiation because write dup
|
||||
* make write side write only and read side read only */
|
||||
#if defined(HAVE_WRITE_DUP) && defined(HAVE_SECURE_RENEGOTIATION)
|
||||
#error "WRITE DUP and SECURE RENEGOTIATION cannot both be on"
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SGX
|
||||
#define WOLFCRYPT_ONLY /* limitation until IO resolved */
|
||||
#define SINGLE_THREADED
|
||||
|
@ -343,7 +343,8 @@
|
||||
DYNAMIC_TYPE_MUTEX = 59,
|
||||
DYNAMIC_TYPE_PKCS7 = 60,
|
||||
DYNAMIC_TYPE_ASN1 = 61,
|
||||
DYNAMIC_TYPE_LOG = 62
|
||||
DYNAMIC_TYPE_LOG = 62,
|
||||
DYNAMIC_TYPE_WRITEDUP = 63
|
||||
};
|
||||
|
||||
/* max error buffer string size */
|
||||
|
Loading…
Reference in New Issue
Block a user