mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 04:04:39 +02:00
add DTLS session export option
This commit is contained in:
17
configure.ac
17
configure.ac
@@ -2526,6 +2526,23 @@ fi
|
|||||||
AM_CONDITIONAL([BUILD_ASYNCCRYPT], [test "x$ENABLED_ASYNCCRYPT" = "xyes"])
|
AM_CONDITIONAL([BUILD_ASYNCCRYPT], [test "x$ENABLED_ASYNCCRYPT" = "xyes"])
|
||||||
|
|
||||||
|
|
||||||
|
# Session Export
|
||||||
|
AC_ARG_ENABLE([sessionexport],
|
||||||
|
[AS_HELP_STRING([--enable-sessionexport],[Enable export and import of sessions (default: disabled)])],
|
||||||
|
[ ENABLED_SESSIONEXPORT=$enableval ],
|
||||||
|
[ ENABLED_SESSIONEXPORT=no ]
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "$ENABLED_SESSIONEXPORT" = "yes"
|
||||||
|
then
|
||||||
|
if test "$ENABLED_DTLS" = "no"
|
||||||
|
then
|
||||||
|
AC_MSG_ERROR([Only DTLS supported with session export])
|
||||||
|
fi
|
||||||
|
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SESSION_EXPORT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# check if PSK was enabled for conditionally running psk.test script
|
# check if PSK was enabled for conditionally running psk.test script
|
||||||
AM_CONDITIONAL([BUILD_PSK], [test "x$ENABLED_PSK" = "xyes"])
|
AM_CONDITIONAL([BUILD_PSK], [test "x$ENABLED_PSK" = "xyes"])
|
||||||
|
|
||||||
|
@@ -1403,6 +1403,17 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
strncpy(resumeMsg, "GET /index.html HTTP/1.0\r\n\r\n", resumeSz);
|
strncpy(resumeMsg, "GET /index.html HTTP/1.0\r\n\r\n", resumeSz);
|
||||||
resumeMsg[resumeSz] = '\0';
|
resumeMsg[resumeSz] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* allow some time for exporting the session */
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
|
||||||
|
#ifdef USE_WINDOWS_API
|
||||||
|
Sleep(500);
|
||||||
|
#elif defined(WOLFSSL_TIRTOS)
|
||||||
|
Task_sleep(1);
|
||||||
|
#else
|
||||||
|
sleep(1);
|
||||||
|
#endif
|
||||||
|
#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
|
||||||
if (wolfSSL_write(ssl, msg, msgSz) != msgSz)
|
if (wolfSSL_write(ssl, msg, msgSz) != msgSz)
|
||||||
err_sys("SSL_write failed");
|
err_sys("SSL_write failed");
|
||||||
|
|
||||||
@@ -1521,6 +1532,18 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
printf("Getting ALPN protocol name failed\n");
|
printf("Getting ALPN protocol name failed\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* allow some time for exporting the session */
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
|
||||||
|
#ifdef USE_WINDOWS_API
|
||||||
|
Sleep(500);
|
||||||
|
#elif defined(WOLFSSL_TIRTOS)
|
||||||
|
Task_sleep(1);
|
||||||
|
#else
|
||||||
|
sleep(1);
|
||||||
|
#endif
|
||||||
|
#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
|
||||||
|
|
||||||
if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)
|
if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)
|
||||||
err_sys("SSL_write failed");
|
err_sys("SSL_write failed");
|
||||||
|
|
||||||
|
432
src/internal.c
432
src/internal.c
@@ -48,7 +48,8 @@
|
|||||||
#include "libntruencrypt/ntru_crypto.h"
|
#include "libntruencrypt/ntru_crypto.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
|
#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \
|
||||||
|
defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG)
|
||||||
#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
|
#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
|
||||||
#if MQX_USE_IO_OLD
|
#if MQX_USE_IO_OLD
|
||||||
#include <fio.h>
|
#include <fio.h>
|
||||||
@@ -469,6 +470,427 @@ static INLINE void ato32(const byte* c, word32* u32)
|
|||||||
#endif /* HAVE_LIBZ */
|
#endif /* HAVE_LIBZ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
/* copy over necessary information from Options struct to buffer
|
||||||
|
* On success returns 0 on failure returns a negative value */
|
||||||
|
static int dtls_export_new(byte* exp, word32 len, byte ver, WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
int idx = 0;
|
||||||
|
word16 zero = 0;
|
||||||
|
Options* options = &ssl->options;
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("dtls_export_new");
|
||||||
|
|
||||||
|
if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* these options are kept and sent to indicate verify status and strength
|
||||||
|
* of handshake */
|
||||||
|
exp[idx++] = options->sendVerify;
|
||||||
|
exp[idx++] = options->verifyPeer;
|
||||||
|
exp[idx++] = options->verifyNone;
|
||||||
|
exp[idx++] = options->downgrade;
|
||||||
|
#ifndef NO_DH
|
||||||
|
c16toa(options->minDhKeySz, exp + idx); idx += 2;
|
||||||
|
c16toa(options->dhKeySz, exp + idx); idx += 2;
|
||||||
|
#else
|
||||||
|
c16toa(zero, exp + idx); idx += 2;
|
||||||
|
c16toa(zero, exp + idx); idx += 2;
|
||||||
|
#endif
|
||||||
|
#ifndef NO_RSA
|
||||||
|
c16toa((word16)(options->minRsaKeySz), exp + idx); idx += 2;
|
||||||
|
#else
|
||||||
|
c16toa(zero, exp + idx); idx += 2;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ECC
|
||||||
|
c16toa((word16)(options->minEccKeySz), exp + idx); idx += 2;
|
||||||
|
#else
|
||||||
|
c16toa(zero, exp + idx); idx += 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* these options are kept to indicate state and behavior */
|
||||||
|
#ifndef NO_PSK
|
||||||
|
exp[idx++] = options->havePSK;
|
||||||
|
#else
|
||||||
|
exp[idx++] = 0;
|
||||||
|
#endif
|
||||||
|
exp[idx++] = options->sessionCacheOff;
|
||||||
|
exp[idx++] = options->sessionCacheFlushOff;
|
||||||
|
exp[idx++] = options->side;
|
||||||
|
exp[idx++] = options->resuming;
|
||||||
|
exp[idx++] = options->haveSessionId;
|
||||||
|
exp[idx++] = options->tls;
|
||||||
|
exp[idx++] = options->tls1_1;
|
||||||
|
exp[idx++] = options->dtls;
|
||||||
|
exp[idx++] = options->connReset;
|
||||||
|
exp[idx++] = options->isClosed;
|
||||||
|
exp[idx++] = options->closeNotify;
|
||||||
|
exp[idx++] = options->sentNotify;
|
||||||
|
exp[idx++] = options->usingCompression;
|
||||||
|
exp[idx++] = options->haveRSA;
|
||||||
|
exp[idx++] = options->haveECC;
|
||||||
|
exp[idx++] = options->haveDH;
|
||||||
|
exp[idx++] = options->haveNTRU;
|
||||||
|
exp[idx++] = options->haveQSH;
|
||||||
|
exp[idx++] = options->haveECDSAsig;
|
||||||
|
exp[idx++] = options->haveStaticECC;
|
||||||
|
exp[idx++] = options->havePeerVerify;
|
||||||
|
exp[idx++] = options->usingPSK_cipher;
|
||||||
|
exp[idx++] = options->usingAnon_cipher;
|
||||||
|
exp[idx++] = options->sendAlertState;
|
||||||
|
exp[idx++] = options->partialWrite;
|
||||||
|
exp[idx++] = options->quietShutdown;
|
||||||
|
exp[idx++] = options->groupMessages;
|
||||||
|
#ifdef HAVE_POLY1305
|
||||||
|
exp[idx++] = options->oldPoly;
|
||||||
|
#else
|
||||||
|
exp[idx++] = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ANON
|
||||||
|
exp[idx++] = options->haveAnon;
|
||||||
|
#else
|
||||||
|
exp[idx++] = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
exp[idx++] = options->createTicket;
|
||||||
|
exp[idx++] = options->useTicket;
|
||||||
|
#else
|
||||||
|
exp[idx++] = 0;
|
||||||
|
exp[idx++] = 0;
|
||||||
|
#endif
|
||||||
|
exp[idx++] = options->processReply;
|
||||||
|
exp[idx++] = options->cipherSuite0;
|
||||||
|
exp[idx++] = options->cipherSuite;
|
||||||
|
exp[idx++] = options->serverState;
|
||||||
|
exp[idx++] = options->clientState;
|
||||||
|
exp[idx++] = options->handShakeState;
|
||||||
|
exp[idx++] = options->handShakeDone;
|
||||||
|
exp[idx++] = options->minDowngrade;
|
||||||
|
exp[idx++] = options->connectState;
|
||||||
|
exp[idx++] = options->acceptState;
|
||||||
|
exp[idx++] = options->keyShareState;
|
||||||
|
|
||||||
|
|
||||||
|
/* version of connection */
|
||||||
|
exp[idx++] = ssl->version.major;
|
||||||
|
exp[idx++] = ssl->version.minor;
|
||||||
|
|
||||||
|
(void)zero;
|
||||||
|
(void)ver;
|
||||||
|
|
||||||
|
/* check if changes were made and notify of need to update export version */
|
||||||
|
if (idx != DTLS_EXPORT_OPT_SZ) {
|
||||||
|
WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of wolfSSL export");
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
WOLFSSL_LEAVE("dtls_export_new", 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* copy items from Export struct to Options struct
|
||||||
|
* On success returns 0 on failure returns a negative value */
|
||||||
|
static int dtls_export_load(byte* exp, word32 len, byte ver, WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
int idx = 0;
|
||||||
|
Options* options = &ssl->options;
|
||||||
|
|
||||||
|
if (ver != 1) {
|
||||||
|
WOLFSSL_MSG("Export version not supported");
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* these options are kept and sent to indicate verify status and strength
|
||||||
|
* of handshake */
|
||||||
|
options->sendVerify = exp[idx++];
|
||||||
|
options->verifyPeer = exp[idx++];
|
||||||
|
options->verifyNone = exp[idx++];
|
||||||
|
options->downgrade = exp[idx++];
|
||||||
|
#ifndef NO_DH
|
||||||
|
ato16(exp + idx, &(options->minDhKeySz)); idx += 2;
|
||||||
|
ato16(exp + idx, &(options->dhKeySz)); idx += 2;
|
||||||
|
#else
|
||||||
|
idx += 2;
|
||||||
|
idx += 2;
|
||||||
|
#endif
|
||||||
|
#ifndef NO_RSA
|
||||||
|
ato16(exp + idx, (word16*)&(options->minRsaKeySz)); idx += 2;
|
||||||
|
#else
|
||||||
|
idx += 2;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ECC
|
||||||
|
ato16(exp + idx, (word16*)&(options->minEccKeySz)); idx += 2;
|
||||||
|
#else
|
||||||
|
idx += 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* these options are kept to indicate state and behavior */
|
||||||
|
#ifndef NO_PSK
|
||||||
|
options->havePSK = exp[idx++];
|
||||||
|
#else
|
||||||
|
idx++;
|
||||||
|
#endif
|
||||||
|
options->sessionCacheOff = exp[idx++];
|
||||||
|
options->sessionCacheFlushOff = exp[idx++];
|
||||||
|
options->side = exp[idx++];
|
||||||
|
options->resuming = exp[idx++];
|
||||||
|
options->haveSessionId = exp[idx++];
|
||||||
|
options->tls = exp[idx++];
|
||||||
|
options->tls1_1 = exp[idx++];
|
||||||
|
options->dtls = exp[idx++];
|
||||||
|
options->connReset = exp[idx++];
|
||||||
|
options->isClosed = exp[idx++];
|
||||||
|
options->closeNotify = exp[idx++];
|
||||||
|
options->sentNotify = exp[idx++];
|
||||||
|
options->usingCompression = exp[idx++];
|
||||||
|
options->haveRSA = exp[idx++];
|
||||||
|
options->haveECC = exp[idx++];
|
||||||
|
options->haveDH = exp[idx++];
|
||||||
|
options->haveNTRU = exp[idx++];
|
||||||
|
options->haveQSH = exp[idx++];
|
||||||
|
options->haveECDSAsig = exp[idx++];
|
||||||
|
options->haveStaticECC = exp[idx++];
|
||||||
|
options->havePeerVerify = exp[idx++];
|
||||||
|
options->usingPSK_cipher = exp[idx++];
|
||||||
|
options->usingAnon_cipher = exp[idx++];
|
||||||
|
options->sendAlertState = exp[idx++];
|
||||||
|
options->partialWrite = exp[idx++];
|
||||||
|
options->quietShutdown = exp[idx++];
|
||||||
|
options->groupMessages = exp[idx++];
|
||||||
|
#ifdef HAVE_POLY1305
|
||||||
|
options->oldPoly = exp[idx++]; /* set when to use old rfc way of poly*/
|
||||||
|
#else
|
||||||
|
idx++;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ANON
|
||||||
|
options->haveAnon = exp[idx++]; /* User wants to allow Anon suites */
|
||||||
|
#else
|
||||||
|
idx++;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
options->createTicket = exp[idx++]; /* Server to create new Ticket */
|
||||||
|
options->useTicket = exp[idx++]; /* Use Ticket not session cache */
|
||||||
|
#else
|
||||||
|
idx++;
|
||||||
|
idx++;
|
||||||
|
#endif
|
||||||
|
options->processReply = exp[idx++];
|
||||||
|
options->cipherSuite0 = exp[idx++];
|
||||||
|
options->cipherSuite = exp[idx++];
|
||||||
|
options->serverState = exp[idx++];
|
||||||
|
options->clientState = exp[idx++];
|
||||||
|
options->handShakeState = exp[idx++];
|
||||||
|
options->handShakeDone = exp[idx++];
|
||||||
|
options->minDowngrade = exp[idx++];
|
||||||
|
options->connectState = exp[idx++];
|
||||||
|
options->acceptState = exp[idx++];
|
||||||
|
options->keyShareState = exp[idx++];
|
||||||
|
|
||||||
|
/* version of connection */
|
||||||
|
if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) {
|
||||||
|
WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2");
|
||||||
|
return VERSION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session
|
||||||
|
* buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
|
||||||
|
* passed in.
|
||||||
|
* On success returns the size of serialized session.*/
|
||||||
|
int wolfSSL_dtls_export(byte* buf, word32 sz, WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
word32 idx = 0;
|
||||||
|
word32 totalLen = 0;
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("wolfSSL_dtls_export");
|
||||||
|
|
||||||
|
if (buf == NULL || ssl == NULL) {
|
||||||
|
WOLFSSL_LEAVE("wolfSSL_dtls_export", BAD_FUNC_ARG);
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */
|
||||||
|
/* each of the following have a 2 byte length before data */
|
||||||
|
totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ;
|
||||||
|
totalLen += DTLS_EXPORT_LEN + sizeof(Keys);
|
||||||
|
totalLen += DTLS_EXPORT_LEN + sizeof(CipherSpecs);
|
||||||
|
totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz;
|
||||||
|
|
||||||
|
if (totalLen > sz) {
|
||||||
|
WOLFSSL_LEAVE("wolfSSL_dtls_export", BUFFER_E);
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[idx++] = (byte)DTLS_EXPORT_PRO;
|
||||||
|
buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) |
|
||||||
|
((byte)DTLS_EXPORT_VERSION & 0X0F);
|
||||||
|
|
||||||
|
c16toa((word16)(totalLen - DTLS_EXPORT_LEN), buf + idx);
|
||||||
|
idx += DTLS_EXPORT_LEN;
|
||||||
|
|
||||||
|
/* if compiled with debug options then print the version, protocol, size */
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
|
||||||
|
{
|
||||||
|
char debug[256];
|
||||||
|
snprintf(debug, sizeof(debug), "Exporting DTLS session\n"
|
||||||
|
"\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
|
||||||
|
, (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), totalLen - 2);
|
||||||
|
WOLFSSL_MSG(debug);
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
|
||||||
|
|
||||||
|
c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
|
||||||
|
if ((ret = dtls_export_new(buf + idx, sz - idx, DTLS_EXPORT_VERSION,
|
||||||
|
ssl)) != 0) {
|
||||||
|
WOLFSSL_LEAVE("wolfSSL_dtls_export", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
idx += DTLS_EXPORT_OPT_SZ;
|
||||||
|
|
||||||
|
/* export keys struct and dtls state */
|
||||||
|
c16toa((word16)sizeof(Keys), buf + idx);
|
||||||
|
idx += DTLS_EXPORT_LEN;
|
||||||
|
XMEMCPY(buf + idx, (byte*)&ssl->keys, sizeof(Keys));
|
||||||
|
idx += sizeof(Keys);
|
||||||
|
|
||||||
|
c16toa((word16)sizeof(CipherSpecs), buf + idx);
|
||||||
|
idx += DTLS_EXPORT_LEN;
|
||||||
|
XMEMCPY(buf + idx, (byte*)&ssl->specs, sizeof(CipherSpecs));
|
||||||
|
idx += sizeof(CipherSpecs);
|
||||||
|
|
||||||
|
c16toa((word16)ssl->buffers.dtlsCtx.peer.sz, buf + idx);
|
||||||
|
idx += DTLS_EXPORT_LEN;
|
||||||
|
XMEMCPY(buf + idx, ssl->buffers.dtlsCtx.peer.sa,
|
||||||
|
ssl->buffers.dtlsCtx.peer.sz);
|
||||||
|
idx += ssl->buffers.dtlsCtx.peer.sz;
|
||||||
|
|
||||||
|
WOLFSSL_LEAVE("wolfSSL_dtls_export", idx);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* On success return amount of buffer consumed */
|
||||||
|
int wolfSSL_dtls_import_internal(byte* buf, word32 sz, WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
word32 idx = 0;
|
||||||
|
word16 length = 0;
|
||||||
|
int version;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("wolfSSL_dtls_import_internal");
|
||||||
|
/* check at least enough room for protocol and length */
|
||||||
|
if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanity check on protocol ID and size of buffer */
|
||||||
|
if (buf[idx++] != (byte)DTLS_EXPORT_PRO ||
|
||||||
|
(buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
|
||||||
|
/* don't increment on second idx to next get version */
|
||||||
|
WOLFSSL_MSG("Incorrect protocol");
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
version = buf[idx++] & 0x0F;
|
||||||
|
|
||||||
|
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
|
||||||
|
if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if compiled with debug options then print the version, protocol, size */
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
|
||||||
|
{
|
||||||
|
char debug[256];
|
||||||
|
snprintf(debug, sizeof(debug), "Importing DTLS session\n"
|
||||||
|
"\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
|
||||||
|
, (int)version, buf[0], (buf[1] >> 4), length);
|
||||||
|
WOLFSSL_MSG(debug);
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
|
||||||
|
|
||||||
|
/* perform sanity checks and extract Options information used */
|
||||||
|
if (DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ + idx > sz) {
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
|
||||||
|
if (length != DTLS_EXPORT_OPT_SZ) {
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
if ((ret = dtls_export_load(buf + idx, length, version, ssl)) != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
idx += length;
|
||||||
|
|
||||||
|
/* perform sanity checks and extract Keys struct */
|
||||||
|
if (DTLS_EXPORT_LEN + sizeof(Keys) + idx > sz) {
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
|
||||||
|
if (length < sizeof(Keys) || length + idx > sz) {
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
XMEMCPY(&ssl->keys, buf + idx, sizeof(Keys));
|
||||||
|
idx += sizeof(Keys);
|
||||||
|
|
||||||
|
/* perform sanity checks and extract CipherSpecs struct */
|
||||||
|
if (DTLS_EXPORT_LEN + sizeof(CipherSpecs) + idx > sz) {
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
|
||||||
|
if ( length != sizeof(CipherSpecs)) {
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
XMEMCPY(&ssl->specs, buf + idx, length);
|
||||||
|
idx += length;
|
||||||
|
|
||||||
|
/* perform sanity checks and extract DTLS peer info */
|
||||||
|
if (DTLS_EXPORT_LEN + idx > sz) {
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
|
||||||
|
ssl->buffers.dtlsCtx.peer.sz = length;
|
||||||
|
|
||||||
|
if (idx + ssl->buffers.dtlsCtx.peer.sz > sz) {
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* peer sa is free'd in SSL_ResourceFree */
|
||||||
|
ssl->buffers.dtlsCtx.peer.sa = XMALLOC(ssl->buffers.dtlsCtx.peer.sz,
|
||||||
|
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (ssl->buffers.dtlsCtx.peer.sa == NULL) {
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(ssl->buffers.dtlsCtx.peer.sa, buf + idx,
|
||||||
|
ssl->buffers.dtlsCtx.peer.sz);
|
||||||
|
idx += ssl->buffers.dtlsCtx.peer.sz;
|
||||||
|
|
||||||
|
SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
|
||||||
|
|
||||||
|
/* set hmac function to use when verifying */
|
||||||
|
if (ssl->options.tls == 1 || ssl->options.tls1_1 == 1 ||
|
||||||
|
ssl->options.dtls == 1) {
|
||||||
|
ssl->hmac = TLS_hmac;
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_DTLS */
|
||||||
|
#endif /* WOLFSSL_SESSION_EXPORT */
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_WOLF_EVENT
|
#ifdef HAVE_WOLF_EVENT
|
||||||
int wolfSSL_EventInit(WOLFSSL* ssl, WOLF_EVENT_TYPE type)
|
int wolfSSL_EventInit(WOLFSSL* ssl, WOLF_EVENT_TYPE type)
|
||||||
{
|
{
|
||||||
@@ -2316,7 +2738,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
|||||||
ssl->options.haveECC, ssl->options.haveStaticECC,
|
ssl->options.haveECC, ssl->options.haveStaticECC,
|
||||||
ssl->options.side);
|
ssl->options.side);
|
||||||
|
|
||||||
#ifndef NO_CERTS
|
#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
|
||||||
/* make sure server has cert and key unless using PSK or Anon
|
/* make sure server has cert and key unless using PSK or Anon
|
||||||
* This should be true even if just switching ssl ctx */
|
* This should be true even if just switching ssl ctx */
|
||||||
if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
|
if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
|
||||||
@@ -2327,6 +2749,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
ssl->dtls_export = ctx->dtls_export; /* export function for session */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
return SSL_SUCCESS;
|
return SSL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
103
src/ssl.c
103
src/ssl.c
@@ -153,6 +153,103 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz)
|
||||||
|
{
|
||||||
|
WOLFSSL_ENTER("wolfSSL_session_import");
|
||||||
|
|
||||||
|
if (ssl == NULL || buf == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanity checks on buffer and protocol are done in internal function */
|
||||||
|
return wolfSSL_dtls_import_internal(buf, sz, ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func)
|
||||||
|
{
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export");
|
||||||
|
|
||||||
|
/* purposefully allow func to be NULL */
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->dtls_export = func;
|
||||||
|
|
||||||
|
return SSL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func)
|
||||||
|
{
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("wolfSSL_dtls_set_export");
|
||||||
|
|
||||||
|
/* purposefully allow func to be NULL */
|
||||||
|
if (ssl == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl->dtls_export = func;
|
||||||
|
|
||||||
|
return SSL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wolfSSL_send_session(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
byte* buf;
|
||||||
|
word16 bufSz = MAX_EXPORT_BUFFER;
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("wolfSSL_send_session");
|
||||||
|
|
||||||
|
if (ssl == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (buf == NULL) {
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if not DTLS do nothing */
|
||||||
|
if (!ssl->options.dtls) {
|
||||||
|
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
WOLFSSL_MSG("Currently only DTLS export is supported");
|
||||||
|
return SSL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl->dtls_export) {
|
||||||
|
/* copy over keys, options, and dtls state struct */
|
||||||
|
ret = wolfSSL_dtls_export(buf, bufSz, ssl);
|
||||||
|
if (ret < 0) {
|
||||||
|
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if no error ret has size of buffer */
|
||||||
|
ret = ssl->dtls_export(ssl, buf, ret, NULL);
|
||||||
|
if (ret != SSL_SUCCESS) {
|
||||||
|
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return SSL_SUCCESS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return SSL_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_DTLS */
|
||||||
|
#endif /* WOLFSSL_SESSION_EXPORT */
|
||||||
|
|
||||||
|
|
||||||
/* prevent multiple mutex initializations */
|
/* prevent multiple mutex initializations */
|
||||||
static volatile int initRefCount = 0;
|
static volatile int initRefCount = 0;
|
||||||
@@ -6544,6 +6641,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
|
|||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
else {
|
else {
|
||||||
ssl->options.dtlsHsRetain = 1;
|
ssl->options.dtlsHsRetain = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSL_DTLS */
|
#endif /* WOLFSSL_DTLS */
|
||||||
|
|
||||||
@@ -6832,6 +6930,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
|
|||||||
}
|
}
|
||||||
#endif /* WOLFSSL_DTLS */
|
#endif /* WOLFSSL_DTLS */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT
|
||||||
|
WOLFSSL_MSG("sending session");
|
||||||
|
wolfSSL_send_session(ssl);
|
||||||
|
#endif
|
||||||
|
|
||||||
WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS);
|
WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS);
|
||||||
return SSL_SUCCESS;
|
return SSL_SUCCESS;
|
||||||
|
|
||||||
|
@@ -369,7 +369,9 @@ static void test_server_wolfSSL_new(void)
|
|||||||
|
|
||||||
/* invalid context */
|
/* invalid context */
|
||||||
AssertNull(ssl = wolfSSL_new(NULL));
|
AssertNull(ssl = wolfSSL_new(NULL));
|
||||||
|
#ifndef WOLFSSL_SESSION_EXPORT
|
||||||
AssertNull(ssl = wolfSSL_new(ctx_nocert));
|
AssertNull(ssl = wolfSSL_new(ctx_nocert));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
AssertNotNull(ssl = wolfSSL_new(ctx));
|
AssertNotNull(ssl = wolfSSL_new(ctx));
|
||||||
|
@@ -949,7 +949,11 @@ enum Misc {
|
|||||||
DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */
|
DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */
|
||||||
DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */
|
DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */
|
||||||
DTLS_POOL_SZ = 5, /* buffers to hold in the retry pool */
|
DTLS_POOL_SZ = 5, /* buffers to hold in the retry pool */
|
||||||
|
DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */
|
||||||
|
DTLS_EXPORT_VERSION = 1, /* wolfSSL version for serialized session */
|
||||||
|
DTLS_EXPORT_OPT_SZ = 57, /* amount of bytes used from Options */
|
||||||
|
DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */
|
||||||
|
MAX_EXPORT_BUFFER = 500, /* max size of buffer for exporting */
|
||||||
FINISHED_LABEL_SZ = 15, /* TLS finished label size */
|
FINISHED_LABEL_SZ = 15, /* TLS finished label size */
|
||||||
TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
|
TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
|
||||||
MASTER_LABEL_SZ = 13, /* TLS master secret label sz */
|
MASTER_LABEL_SZ = 13, /* TLS master secret label sz */
|
||||||
@@ -1195,6 +1199,8 @@ typedef struct ProtocolVersion {
|
|||||||
} WOLFSSL_PACK ProtocolVersion;
|
} WOLFSSL_PACK ProtocolVersion;
|
||||||
|
|
||||||
|
|
||||||
|
WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(byte* buf, word32 sz, WOLFSSL* ssl);
|
||||||
|
WOLFSSL_LOCAL int wolfSSL_dtls_export(byte* buf, word32 sz, WOLFSSL* ssl);
|
||||||
WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void);
|
WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void);
|
||||||
WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void);
|
WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void);
|
||||||
WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void);
|
WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void);
|
||||||
@@ -1369,7 +1375,10 @@ int SetCipherList(Suites*, const char* list);
|
|||||||
typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
|
typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
|
||||||
unsigned char*, unsigned int);
|
unsigned char*, unsigned int);
|
||||||
#endif /* PSK_TYPES_DEFINED */
|
#endif /* PSK_TYPES_DEFINED */
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
typedef int (*wc_dtls_export)(WOLFSSL* ssl,
|
||||||
|
unsigned char* exportBuffer, unsigned int sz, void* userCtx);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_NETX
|
#ifdef HAVE_NETX
|
||||||
WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx);
|
WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx);
|
||||||
@@ -1575,7 +1584,8 @@ typedef struct WOLFSSL_DTLS_CTX {
|
|||||||
|
|
||||||
#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */
|
#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */
|
||||||
|
|
||||||
/* keys and secrets */
|
/* keys and secrets
|
||||||
|
* keep as a constant size (no additional ifdefs) for session export */
|
||||||
typedef struct Keys {
|
typedef struct Keys {
|
||||||
byte client_write_MAC_secret[MAX_DIGEST_SIZE]; /* max sizes */
|
byte client_write_MAC_secret[MAX_DIGEST_SIZE]; /* max sizes */
|
||||||
byte server_write_MAC_secret[MAX_DIGEST_SIZE];
|
byte server_write_MAC_secret[MAX_DIGEST_SIZE];
|
||||||
@@ -1583,7 +1593,7 @@ typedef struct Keys {
|
|||||||
byte server_write_key[AES_256_KEY_SIZE];
|
byte server_write_key[AES_256_KEY_SIZE];
|
||||||
byte client_write_IV[MAX_WRITE_IV_SZ]; /* max sizes */
|
byte client_write_IV[MAX_WRITE_IV_SZ]; /* max sizes */
|
||||||
byte server_write_IV[MAX_WRITE_IV_SZ];
|
byte server_write_IV[MAX_WRITE_IV_SZ];
|
||||||
#ifdef HAVE_AEAD
|
#if defined(HAVE_AEAD) || defined(WOLFSSL_SESSION_EXPORT)
|
||||||
byte aead_exp_IV[AEAD_MAX_EXP_SZ];
|
byte aead_exp_IV[AEAD_MAX_EXP_SZ];
|
||||||
byte aead_enc_imp_IV[AEAD_MAX_IMP_SZ];
|
byte aead_enc_imp_IV[AEAD_MAX_IMP_SZ];
|
||||||
byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
|
byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
|
||||||
@@ -1938,6 +1948,7 @@ struct WOLFSSL_CTX {
|
|||||||
CallbackIOSend CBIOSend;
|
CallbackIOSend CBIOSend;
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
CallbackGenCookie CBIOCookie; /* gen cookie callback */
|
CallbackGenCookie CBIOCookie; /* gen cookie callback */
|
||||||
|
wc_dtls_export dtls_export; /* export function for DTLS session */
|
||||||
#endif
|
#endif
|
||||||
VerifyCallback verifyCallback; /* cert verification callback */
|
VerifyCallback verifyCallback; /* cert verification callback */
|
||||||
word32 timeout; /* session timeout */
|
word32 timeout; /* session timeout */
|
||||||
@@ -2033,7 +2044,8 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* All cipher suite related info */
|
/* All cipher suite related info
|
||||||
|
* Keep as a constant size (no ifdefs) for session export */
|
||||||
typedef struct CipherSpecs {
|
typedef struct CipherSpecs {
|
||||||
word16 key_size;
|
word16 key_size;
|
||||||
word16 iv_size;
|
word16 iv_size;
|
||||||
@@ -2712,6 +2724,7 @@ struct WOLFSSL {
|
|||||||
DtlsMsg* dtls_msg_list;
|
DtlsMsg* dtls_msg_list;
|
||||||
void* IOCB_CookieCtx; /* gen cookie ctx */
|
void* IOCB_CookieCtx; /* gen cookie ctx */
|
||||||
word32 dtls_expected_rx;
|
word32 dtls_expected_rx;
|
||||||
|
wc_dtls_export dtls_export; /* export function for session */
|
||||||
#endif
|
#endif
|
||||||
#ifdef WOLFSSL_CALLBACKS
|
#ifdef WOLFSSL_CALLBACKS
|
||||||
HandShakeInfo handShakeInfo; /* info saved during handshake */
|
HandShakeInfo handShakeInfo; /* info saved during handshake */
|
||||||
|
@@ -225,6 +225,17 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void);
|
|||||||
WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int);
|
WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SESSION_EXPORT
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
typedef int (*wc_dtls_export)(WOLFSSL* ssl,
|
||||||
|
unsigned char* exportBuffer, unsigned int sz, void* userCtx);
|
||||||
|
WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz);
|
||||||
|
WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func);
|
||||||
|
WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func);
|
||||||
|
WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
|
||||||
|
#endif /* WOLFSSL_DTLS */
|
||||||
|
#endif /* WOLFSSL_SESSION_EXPORT */
|
||||||
|
|
||||||
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
|
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
|
||||||
|
|
||||||
WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int);
|
WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int);
|
||||||
|
Reference in New Issue
Block a user