Merge pull request #414 from JacobBarthelmeh/DTLS-MultiCore

Dtls multi core
This commit is contained in:
toddouska
2016-05-17 17:39:18 -07:00
8 changed files with 1107 additions and 15 deletions

View File

@ -2596,6 +2596,23 @@ fi
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
AM_CONDITIONAL([BUILD_PSK], [test "x$ENABLED_PSK" = "xyes"])

View File

@ -1421,6 +1421,17 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
strncpy(resumeMsg, "GET /index.html HTTP/1.0\r\n\r\n", resumeSz);
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)
err_sys("SSL_write failed");
@ -1539,6 +1550,18 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
printf("Getting ALPN protocol name failed\n");
}
#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)
err_sys("SSL_write failed");

View File

@ -48,7 +48,8 @@
#include "libntruencrypt/ntru_crypto.h"
#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 MQX_USE_IO_OLD
#include <fio.h>
@ -346,7 +347,7 @@ static INLINE void c16toa(word16 u16, byte* c)
#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
|| defined(HAVE_AESGCM)
|| defined(HAVE_AESGCM) || defined(WOLFSSL_SESSION_EXPORT)
/* convert 32 bit integer to opaque */
static INLINE void c32toa(word32 u32, byte* c)
{
@ -355,6 +356,21 @@ static INLINE void c32toa(word32 u32, byte* c)
c[2] = (u32 >> 8) & 0xff;
c[3] = u32 & 0xff;
}
#if defined(WOLFSSL_SESSION_EXPORT)
/* convert 64 bit integer to opaque */
static INLINE void c64toa(word64 u64, byte* c)
{
c[0] = (u64 >> 56) & 0xff;
c[1] = (u64 >> 48) & 0xff;
c[2] = (u64 >> 40) & 0xff;
c[3] = (u64 >> 32) & 0xff;
c[4] = (u64 >> 24) & 0xff;
c[5] = (u64 >> 16) & 0xff;
c[6] = (u64 >> 8) & 0xff;
c[7] = u64 & 0xff;
}
#endif /* WOLFSSL_SESSION_EXPORT */
#endif
@ -372,7 +388,8 @@ static INLINE void ato16(const byte* c, word16* u16)
}
#if defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET)
#if defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET) || \
defined(WOLFSSL_SESSION_EXPORT)
/* convert opaque to 32 bit integer */
static INLINE void ato32(const byte* c, word32* u32)
@ -380,6 +397,21 @@ static INLINE void ato32(const byte* c, word32* u32)
*u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}
#if defined(WOLFSSL_SESSION_EXPORT)
/* convert opaque to word64 type */
static INLINE void ato64(const byte* c, word64* u64)
{
/* when doing cast to allow for shift, mask the values */
*u64 = (((word64)c[0] << 56) & 0xff00000000000000) |
(((word64)c[1] << 48) & 0x00ff000000000000) |
(((word64)c[2] << 40) & 0x0000ff0000000000) |
(((word64)c[3] << 32) & 0x000000ff00000000) |
(((word64)c[4] << 24) & 0x00000000ff000000) |
(((word64)c[5] << 16) & 0x0000000000ff0000) |
(((word64)c[6] << 8) & 0x000000000000ff00) |
((word64)c[7] & 0x00000000000000ff);
}
#endif /* WOLFSSL_SESSION_EXPORT */
#endif /* WOLFSSL_DTLS */
@ -469,6 +501,726 @@ static INLINE void ato32(const byte* c, word32* u32)
#endif /* HAVE_LIBZ */
#ifdef WOLFSSL_SESSION_EXPORT
#ifdef WOLFSSL_DTLS
/* serializes the cipher specs struct for exporting */
static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
{
word32 idx = 0;
CipherSpecs* specs;
WOLFSSL_ENTER("ExportCipherSpecState");
if (exp == NULL || ssl == NULL) {
return BAD_FUNC_ARG;
}
specs= &(ssl->specs);
if (DTLS_EXPORT_SPC_SZ > len) {
return BUFFER_E;
}
XMEMSET(exp, 0, DTLS_EXPORT_SPC_SZ);
c16toa(specs->key_size, exp + idx); idx += OPAQUE16_LEN;
c16toa(specs->iv_size, exp + idx); idx += OPAQUE16_LEN;
c16toa(specs->block_size, exp + idx); idx += OPAQUE16_LEN;
c16toa(specs->aead_mac_size, exp + idx); idx += OPAQUE16_LEN;
exp[idx++] = specs->bulk_cipher_algorithm;
exp[idx++] = specs->cipher_type;
exp[idx++] = specs->mac_algorithm;
exp[idx++] = specs->kea;
exp[idx++] = specs->sig_algo;
exp[idx++] = specs->hash_size;
exp[idx++] = specs->pad_size;
exp[idx++] = specs->static_ecdh;
if (idx != DTLS_EXPORT_SPC_SZ) {
WOLFSSL_MSG("DTLS_EXPORT_SPC_SZ needs updated and export version");
return DTLS_EXPORT_VER_E;
}
WOLFSSL_LEAVE("ExportCipherSpecState", idx);
(void)ver;
return idx;
}
/* serializes the key struct for exporting */
static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
{
word32 idx = 0;
byte sz;
Keys* keys;
WOLFSSL_ENTER("ExportKeyState");
if (exp == NULL || ssl == NULL) {
return BAD_FUNC_ARG;
}
keys = &(ssl->keys);
if (DTLS_EXPORT_KEY_SZ > len) {
return BUFFER_E;
}
XMEMSET(exp, 0, DTLS_EXPORT_KEY_SZ);
c32toa(keys->peer_sequence_number, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->peer_sequence_number, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->sequence_number, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->dtls_state.nextEpoch, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->dtls_state.nextSeq, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->dtls_state.curEpoch, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->dtls_state.curSeq, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->dtls_state.prevSeq, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN;
c16toa(keys->dtls_expected_peer_handshake_number, exp + idx);
idx += OPAQUE16_LEN;
c32toa(keys->dtls_sequence_number, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->dtls_prev_sequence_number, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->dtls_epoch, exp + idx); idx += OPAQUE16_LEN;
c16toa(keys->dtls_handshake_number, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->encryptSz, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->padSz, exp + idx); idx += OPAQUE32_LEN;
exp[idx++] = keys->encryptionOn;
exp[idx++] = keys->decryptedCur;
#ifdef WORD64_AVAILABLE
c64toa(keys->dtls_state.window, exp + idx); idx += OPAQUE64_LEN;
c64toa(keys->dtls_state.prevWindow, exp + idx); idx += OPAQUE64_LEN;
#else
c32toa(keys->dtls_state.window, exp + idx); idx += OPAQUE32_LEN;
c32toa(0, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->dtls_state.prevWindow, exp + idx); idx += OPAQUE32_LEN;
c32toa(0, exp + idx); idx += OPAQUE32_LEN;
#endif
#ifdef HAVE_TRUNCATED_HMAC
sz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ: ssl->specs.hash_size;
exp[idx++] = ssl->truncated_hmac;
#else
sz = ssl->specs.hash_size;
exp[idx++] = 0; /* no truncated hmac */
#endif
exp[idx++] = sz;
XMEMCPY(exp + idx, keys->client_write_MAC_secret, sz); idx += sz;
XMEMCPY(exp + idx, keys->server_write_MAC_secret, sz); idx += sz;
sz = ssl->specs.key_size;
exp[idx++] = sz;
XMEMCPY(exp + idx, keys->client_write_key, sz); idx += sz;
XMEMCPY(exp + idx, keys->server_write_key, sz); idx += sz;
sz = ssl->specs.iv_size;
exp[idx++] = sz;
XMEMCPY(exp + idx, keys->client_write_IV, sz); idx += sz;
XMEMCPY(exp + idx, keys->server_write_IV, sz); idx += sz;
XMEMCPY(exp + idx, keys->aead_exp_IV, AEAD_MAX_EXP_SZ);
idx += AEAD_MAX_EXP_SZ;
sz = AEAD_MAX_IMP_SZ;
exp[idx++] = sz;
XMEMCPY(exp + idx, keys->aead_enc_imp_IV, sz); idx += sz;
XMEMCPY(exp + idx, keys->aead_dec_imp_IV, sz); idx += sz;
if (idx > DTLS_EXPORT_KEY_SZ) {
WOLFSSL_MSG("DTLS_EXPORT_KEY_SZ needs updated and export version");
return DTLS_EXPORT_VER_E;
}
WOLFSSL_LEAVE("ExportKeyState", idx);
(void)ver;
return idx;
}
static int ImportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
{
word32 idx = 0;
CipherSpecs* specs;
WOLFSSL_ENTER("ImportCipherSpecState");
if (exp == NULL || ssl == NULL) {
return BAD_FUNC_ARG;
}
specs= &(ssl->specs);
if (DTLS_EXPORT_SPC_SZ > len) {
return BUFFER_E;
}
ato16(exp + idx, &specs->key_size); idx += OPAQUE16_LEN;
ato16(exp + idx, &specs->iv_size); idx += OPAQUE16_LEN;
ato16(exp + idx, &specs->block_size); idx += OPAQUE16_LEN;
ato16(exp + idx, &specs->aead_mac_size); idx += OPAQUE16_LEN;
specs->bulk_cipher_algorithm = exp[idx++];
specs->cipher_type = exp[idx++];
specs->mac_algorithm = exp[idx++];
specs->kea = exp[idx++];
specs->sig_algo = exp[idx++];
specs->hash_size = exp[idx++];
specs->pad_size = exp[idx++];
specs->static_ecdh = exp[idx++];
WOLFSSL_LEAVE("ImportCipherSpecState", idx);
(void)ver;
return idx;
}
static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
{
word32 idx = 0;
byte sz;
Keys* keys;
WOLFSSL_ENTER("ImportKeyState");
if (exp == NULL || ssl == NULL) {
return BAD_FUNC_ARG;
}
keys = &(ssl->keys);
/* check minimum length -- includes byte used for size indicators */
if (len < DTLS_EXPORT_MIN_KEY_SZ) {
return BUFFER_E;
}
ato32(exp + idx, &keys->peer_sequence_number); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->peer_sequence_number); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->sequence_number); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->dtls_state.nextEpoch); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->dtls_state.nextSeq); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->dtls_state.curEpoch); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->dtls_state.curSeq); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->dtls_state.prevSeq); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN;
ato16(exp + idx, &keys->dtls_expected_peer_handshake_number);
idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->dtls_sequence_number); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->dtls_prev_sequence_number); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->dtls_epoch); idx += OPAQUE16_LEN;
ato16(exp + idx, &keys->dtls_handshake_number); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->encryptSz); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->padSz); idx += OPAQUE32_LEN;
keys->encryptionOn = exp[idx++];
keys->decryptedCur = exp[idx++];
#ifdef WORD64_AVAILABLE
ato64(exp + idx, &keys->dtls_state.window); idx += OPAQUE64_LEN;
ato64(exp + idx, &keys->dtls_state.prevWindow); idx += OPAQUE64_LEN;
#else
ato32(exp + idx, &keys->dtls_state.window); idx += OPAQUE32_LEN;
ato32(exp + idx, 0); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->dtls_state.prevWindow); idx += OPAQUE32_LEN;
ato32(exp + idx, 0); idx += OPAQUE32_LEN;
#endif
#ifdef HAVE_TRUNCATED_HMAC
ssl->truncated_hmac = exp[idx++];
#else
idx++; /* no truncated hmac */
#endif
sz = exp[idx++];
if (sz > MAX_DIGEST_SIZE || sz + idx > len) {
return BUFFER_E;
}
XMEMCPY(keys->client_write_MAC_secret, exp + idx, sz); idx += sz;
XMEMCPY(keys->server_write_MAC_secret, exp + idx, sz); idx += sz;
sz = exp[idx++];
if (sz > AES_256_KEY_SIZE || sz + idx > len) {
return BUFFER_E;
}
XMEMCPY(keys->client_write_key, exp + idx, sz); idx += sz;
XMEMCPY(keys->server_write_key, exp + idx, sz); idx += sz;
sz = exp[idx++];
if (sz > MAX_WRITE_IV_SZ || sz + idx > len) {
return BUFFER_E;
}
XMEMCPY(keys->client_write_IV, exp + idx, sz); idx += sz;
XMEMCPY(keys->server_write_IV, exp + idx, sz); idx += sz;
XMEMCPY(keys->aead_exp_IV, exp + idx, AEAD_MAX_EXP_SZ);
idx += AEAD_MAX_EXP_SZ;
sz = exp[idx++];
if (sz > AEAD_MAX_IMP_SZ || sz + idx > len) {
return BUFFER_E;
}
XMEMCPY(keys->aead_enc_imp_IV, exp + idx, sz); idx += sz;
XMEMCPY(keys->aead_dec_imp_IV, exp + idx, sz); idx += sz;
WOLFSSL_LEAVE("ImportKeyState", idx);
(void)ver;
return idx;
}
/* copy over necessary information from Options struct to buffer
* On success returns size of buffer used on failure returns a negative value */
static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
{
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;
}
XMEMSET(exp, 0, DTLS_EXPORT_OPT_SZ);
/* 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 += OPAQUE16_LEN;
c16toa(options->dhKeySz, exp + idx); idx += OPAQUE16_LEN;
#else
c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
#endif
#ifndef NO_RSA
c16toa((word16)(options->minRsaKeySz), exp + idx); idx += OPAQUE16_LEN;
#else
c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
#endif
#ifdef HAVE_ECC
c16toa((word16)(options->minEccKeySz), exp + idx); idx += OPAQUE16_LEN;
#else
c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
#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 DTLS_EXPORT_VER_E;
}
WOLFSSL_LEAVE("dtls_export_new", idx);
return idx;
}
/* copy items from Export struct to Options struct
* On success returns size of buffer used on failure returns a negative value */
static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
{
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 += OPAQUE16_LEN;
ato16(exp + idx, &(options->dhKeySz)); idx += OPAQUE16_LEN;
#else
idx += OPAQUE16_LEN;
idx += OPAQUE16_LEN;
#endif
#ifndef NO_RSA
ato16(exp + idx, (word16*)&(options->minRsaKeySz)); idx += OPAQUE16_LEN;
#else
idx += OPAQUE16_LEN;
#endif
#ifdef HAVE_ECC
ato16(exp + idx, (word16*)&(options->minEccKeySz)); idx += OPAQUE16_LEN;
#else
idx += OPAQUE16_LEN;
#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 idx;
}
/* 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_internal(WOLFSSL* ssl, byte* buf, word32 sz)
{
int ret;
word32 idx = 0;
word32 totalLen = 0;
WOLFSSL_ENTER("wolfSSL_dtls_export_internal");
if (buf == NULL || ssl == NULL) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", 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 + DTLS_EXPORT_KEY_SZ;
totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ;
totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz;
if (totalLen > sz) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E);
return BUFFER_E;
}
buf[idx++] = (byte)DTLS_EXPORT_PRO;
buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) |
((byte)DTLS_EXPORT_VERSION & 0X0F);
idx += DTLS_EXPORT_LEN; /* leave spot for length */
c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
if ((ret = dtls_export_new(ssl, buf + idx, sz - idx,
DTLS_EXPORT_VERSION)) < 0) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
return ret;
}
idx += ret;
/* export keys struct and dtls state -- variable length stored in ret */
idx += DTLS_EXPORT_LEN; /* leave room for length */
if ((ret = ExportKeyState(ssl, buf + idx, sz - idx,
DTLS_EXPORT_VERSION)) < 0) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
return ret;
}
c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret;
/* export of cipher specs struct */
c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
if ((ret = ExportCipherSpecState(ssl, buf + idx, sz - idx,
DTLS_EXPORT_VERSION)) < 0) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
return ret;
}
idx += ret;
/* export of dtls peer information */
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;
/* place total length of exported buffer minus 2 bytes protocol/version */
c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + 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), idx - 2);
WOLFSSL_MSG(debug);
}
#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", idx);
return idx;
}
/* On success return amount of buffer consumed */
int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
{
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) {
WOLFSSL_MSG("Import Options struct error");
return BUFFER_E;
}
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
if (length != DTLS_EXPORT_OPT_SZ) {
WOLFSSL_MSG("Import Options struct error");
return BUFFER_E;
}
if ((ret = dtls_export_load(ssl, buf + idx, length, version)) < 0) {
WOLFSSL_MSG("Import Options struct error");
return ret;
}
idx += length;
/* perform sanity checks and extract Keys struct */
if (DTLS_EXPORT_LEN + idx > sz) {
WOLFSSL_MSG("Import Key struct error");
return BUFFER_E;
}
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) {
WOLFSSL_MSG("Import Key struct error");
return BUFFER_E;
}
if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) {
WOLFSSL_MSG("Import Key struct error");
return ret;
}
idx += ret;
/* perform sanity checks and extract CipherSpecs struct */
if (DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ + idx > sz) {
WOLFSSL_MSG("Import CipherSpecs struct error");
return BUFFER_E;
}
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
if ( length != DTLS_EXPORT_SPC_SZ) {
WOLFSSL_MSG("Import CipherSpecs struct error");
return BUFFER_E;
}
if ((ret = ImportCipherSpecState(ssl, buf + idx, length, version)) < 0) {
WOLFSSL_MSG("Import CipherSpecs struct error");
return ret;
}
idx += length;
/* perform sanity checks and extract DTLS peer info */
if (DTLS_EXPORT_LEN + idx > sz) {
WOLFSSL_MSG("Import DTLS peer info error");
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) {
WOLFSSL_MSG("Import DTLS peer info error");
return BUFFER_E;
}
/* peer sa is free'd in SSL_ResourceFree */
if ((ret = wolfSSL_dtls_set_peer(ssl, buf + idx,
ssl->buffers.dtlsCtx.peer.sz)) != SSL_SUCCESS) {
WOLFSSL_MSG("Import DTLS peer info error");
return ret;
}
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;
}
/* make sure is a valid suite used */
if (wolfSSL_get_cipher(ssl) == NULL) {
WOLFSSL_MSG("Can not match cipher suite imported");
return MATCH_SUITE_ERROR;
}
/* do not allow stream ciphers with DTLS */
if (ssl->specs.cipher_type == stream) {
WOLFSSL_MSG("Can not import stream ciphers for DTLS");
return SANITY_CIPHER_E;
}
return idx;
}
#endif /* WOLFSSL_DTLS */
#endif /* WOLFSSL_SESSION_EXPORT */
#ifdef HAVE_WOLF_EVENT
int wolfSSL_EventInit(WOLFSSL* ssl, WOLF_EVENT_TYPE type)
{
@ -2316,7 +3068,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
ssl->options.haveECC, ssl->options.haveStaticECC,
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
* This should be true even if just switching ssl ctx */
if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
@ -2327,6 +3079,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
}
#endif
#ifdef WOLFSSL_SESSION_EXPORT
#ifdef WOLFSSL_DTLS
ssl->dtls_export = ctx->dtls_export; /* export function for session */
#endif
#endif
return SSL_SUCCESS;
}
@ -10239,6 +10997,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case ECC_KEY_SIZE_E:
return "ECC key too small";
case DTLS_EXPORT_VER_E:
return "Version needs updated after code change or version mismatch";
default :
return "unknown error number";
}

140
src/ssl.c
View File

@ -153,6 +153,136 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n)
}
#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(ssl, buf, sz);
}
/* Sets the function to call for serializing the session. This function is
* called right after the handshake is completed. */
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;
}
/* Sets the function in WOLFSSL struct to call for serializing the session. This
* function is called right after the handshake is completed. */
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;
}
/* This function allows for directly serializing a session rather than using
* callbacks. It has less overhead by removing a temporary buffer and gives
* control over when the session gets serialized. When using callbacks the
* session is always serialized immediatly after the handshake is finished.
*
* buf is the argument to contain the serialized session
* sz is the size of the buffer passed in
* ssl is the WOLFSSL struct to serialize
* returns the size of serialized session on success, 0 on no action, and
* negative value on error */
int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz)
{
WOLFSSL_ENTER("wolfSSL_dtls_export");
if (ssl == NULL || sz == NULL) {
return BAD_FUNC_ARG;
}
if (buf == NULL) {
*sz = MAX_EXPORT_BUFFER;
return 0;
}
/* if not DTLS do nothing */
if (!ssl->options.dtls) {
WOLFSSL_MSG("Currently only DTLS export is supported");
return 0;
}
/* copy over keys, options, and dtls state struct */
return wolfSSL_dtls_export_internal(ssl, buf, *sz);
}
/* returns 0 on 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 0;
}
/* copy over keys, options, and dtls state struct */
ret = wolfSSL_dtls_export_internal(ssl, buf, bufSz);
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 0;
}
#endif /* WOLFSSL_DTLS */
#endif /* WOLFSSL_SESSION_EXPORT */
/* prevent multiple mutex initializations */
static volatile int initRefCount = 0;
@ -6832,6 +6962,16 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
}
#endif /* WOLFSSL_DTLS */
#ifdef WOLFSSL_SESSION_EXPORT
if (ssl->dtls_export) {
if ((ssl->error = wolfSSL_send_session(ssl)) != 0) {
WOLFSSL_MSG("Export DTLS session error");
WOLFSSL_ERROR(ssl->error);
return SSL_FATAL_ERROR;
}
}
#endif
WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS);
return SSL_SUCCESS;

View File

@ -369,7 +369,9 @@ static void test_server_wolfSSL_new(void)
/* invalid context */
AssertNull(ssl = wolfSSL_new(NULL));
#ifndef WOLFSSL_SESSION_EXPORT
AssertNull(ssl = wolfSSL_new(ctx_nocert));
#endif
/* success */
AssertNotNull(ssl = wolfSSL_new(ctx));
@ -491,6 +493,34 @@ static void test_wolfSSL_SetTmpDH_buffer(void)
/* helper functions */
#ifdef HAVE_IO_TESTS_DEPENDENCIES
#ifdef WOLFSSL_SESSION_EXPORT
/* set up function for sending session information */
static int test_export(WOLFSSL* inSsl, byte* buf, word32 sz, void* userCtx)
{
WOLFSSL_CTX* ctx;
WOLFSSL* ssl;
AssertNotNull(inSsl);
AssertNotNull(buf);
AssertIntNE(0, sz);
/* Set ctx to DTLS 1.2 */
ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method());
AssertNotNull(ctx);
ssl = wolfSSL_new(ctx);
AssertNotNull(ssl);
AssertIntGE(wolfSSL_dtls_import(ssl, buf, sz), 0);
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
(void)userCtx;
return SSL_SUCCESS;
}
#endif
static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
{
SOCKET_T sockfd = 0;
@ -709,8 +739,8 @@ done2:
return;
}
/* SNI / ALPN helper functions */
#if defined(HAVE_SNI) || defined(HAVE_ALPN)
/* SNI / ALPN / session export helper functions */
#if defined(HAVE_SNI) || defined(HAVE_ALPN) || defined(WOLFSSL_SESSION_EXPORT)
static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
{
@ -750,6 +780,9 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
#ifdef OPENSSL_EXTRA
wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif
#ifdef WOLFSSL_SESSION_EXPORT
AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_dtls_set_export(ctx, test_export));
#endif
AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCert, 0));
@ -764,9 +797,21 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
callbacks->ctx_ready(ctx);
ssl = wolfSSL_new(ctx);
if (wolfSSL_dtls(ssl)) {
SOCKADDR_IN_T cliAddr;
socklen_t cliLen;
cliLen = sizeof(cliAddr);
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0);
idx = (int)recvfrom(sfd, input, sizeof(input), MSG_PEEK,
(struct sockaddr*)&cliAddr, &cliLen);
AssertIntGT(idx, 0);
wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen);
}
else {
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 1);
CloseSocket(sfd);
}
AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, cfd));
@ -794,6 +839,20 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
}
AssertIntEQ(len, wolfSSL_write(ssl, msg, len));
#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IO_POOL)
if (wolfSSL_dtls(ssl)) {
byte* import;
word32 sz;
wolfSSL_dtls_export(ssl, NULL, &sz);
import = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
AssertNotNull(import);
idx = wolfSSL_dtls_export(ssl, import, &sz);
AssertIntGE(idx, 0);
AssertIntGE(wolfSSL_dtls_import(ssl, import, idx), 0);
XFREE(import, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
#endif
#ifdef WOLFSSL_TIRTOS
Task_yield();
#endif
@ -859,7 +918,12 @@ static void run_wolfssl_client(void* args)
callbacks->ctx_ready(ctx);
ssl = wolfSSL_new(ctx);
if (wolfSSL_dtls(ssl)) {
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 1, ssl);
}
else {
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl);
}
AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, sfd));
if (callbacks->ssl_ready)
@ -892,7 +956,8 @@ static void run_wolfssl_client(void* args)
#endif
}
#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) */
#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) ||
defined(WOLFSSL_SESSION_EXPORT) */
#endif /* io tests dependencies */
@ -950,6 +1015,52 @@ static void test_wolfSSL_read_write(void)
#endif
}
static void test_wolfSSL_dtls_export(void)
{
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \
defined(WOLFSSL_SESSION_EXPORT)
tcp_ready ready;
func_args client_args;
func_args server_args;
THREAD_TYPE serverThread;
callback_functions server_cbf;
callback_functions client_cbf;
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
InitTcpReady(&ready);
/* set using dtls */
XMEMSET(&server_cbf, 0, sizeof(callback_functions));
XMEMSET(&client_cbf, 0, sizeof(callback_functions));
server_cbf.method = wolfDTLSv1_2_server_method;
client_cbf.method = wolfDTLSv1_2_client_method;
server_args.callbacks = &server_cbf;
client_args.callbacks = &client_cbf;
server_args.signal = &ready;
client_args.signal = &ready;
start_thread(run_wolfssl_server, &server_args, &serverThread);
wait_tcp_ready(&server_args);
run_wolfssl_client(&client_args);
join_thread(serverThread);
AssertTrue(client_args.return_code);
AssertTrue(server_args.return_code);
FreeTcpReady(&ready);
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
printf(testingFmt, "wolfSSL_dtls_export()");
printf(resultFmt, passed);
#endif
}
/*----------------------------------------------------------------------------*
| TLS extensions tests
*----------------------------------------------------------------------------*/
@ -1736,6 +1847,7 @@ void ApiTest(void)
test_wolfSSL_SetTmpDH_file();
test_wolfSSL_SetTmpDH_buffer();
test_wolfSSL_read_write();
test_wolfSSL_dtls_export();
/* TLS extensions tests */
test_wolfSSL_UseSNI();

View File

@ -146,6 +146,8 @@ enum wolfSSL_ErrorCodes {
RSA_KEY_SIZE_E = -409, /* RSA key too small */
ECC_KEY_SIZE_E = -410, /* ECC key too small */
DTLS_EXPORT_VER_E = -411, /* export version error */
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
/* begin negotiation parameter errors */

View File

@ -926,6 +926,7 @@ enum Misc {
OPAQUE16_LEN = 2, /* 2 bytes */
OPAQUE24_LEN = 3, /* 3 bytes */
OPAQUE32_LEN = 4, /* 4 bytes */
OPAQUE64_LEN = 8, /* 8 bytes */
COMP_LEN = 1, /* compression length */
CURVE_LEN = 2, /* ecc named curve length */
SERVER_ID_LEN = 20, /* server session id length */
@ -949,7 +950,14 @@ enum Misc {
DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */
DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */
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_KEY_SZ = 331,/* max amount of bytes used from Keys */
DTLS_EXPORT_MIN_KEY_SZ = 75, /* min amount of bytes used from Keys */
DTLS_EXPORT_SPC_SZ = 16, /* amount of bytes used from CipherSpecs */
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 */
TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
MASTER_LABEL_SZ = 13, /* TLS master secret label sz */
@ -1203,6 +1211,14 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void);
#ifdef WOLFSSL_DTLS
WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void);
WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void);
#ifdef WOLFSSL_SESSION_EXPORT
WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf,
word32 sz);
WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf,
word32 sz);
WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
#endif
#endif
@ -1369,7 +1385,10 @@ int SetCipherList(Suites*, const char* list);
typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
unsigned char*, unsigned int);
#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
WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx);
@ -1575,7 +1594,8 @@ typedef struct WOLFSSL_DTLS_CTX {
#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 {
byte client_write_MAC_secret[MAX_DIGEST_SIZE]; /* max sizes */
byte server_write_MAC_secret[MAX_DIGEST_SIZE];
@ -1583,7 +1603,7 @@ typedef struct Keys {
byte server_write_key[AES_256_KEY_SIZE];
byte client_write_IV[MAX_WRITE_IV_SZ]; /* max sizes */
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_enc_imp_IV[AEAD_MAX_IMP_SZ];
byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
@ -1938,6 +1958,7 @@ struct WOLFSSL_CTX {
CallbackIOSend CBIOSend;
#ifdef WOLFSSL_DTLS
CallbackGenCookie CBIOCookie; /* gen cookie callback */
wc_dtls_export dtls_export; /* export function for DTLS session */
#endif
VerifyCallback verifyCallback; /* cert verification callback */
word32 timeout; /* session timeout */
@ -2033,7 +2054,8 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#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 {
word16 key_size;
word16 iv_size;
@ -2712,6 +2734,7 @@ struct WOLFSSL {
DtlsMsg* dtls_msg_list;
void* IOCB_CookieCtx; /* gen cookie ctx */
word32 dtls_expected_rx;
wc_dtls_export dtls_export; /* export function for session */
#endif
#ifdef WOLFSSL_CALLBACKS
HandShakeInfo handShakeInfo; /* info saved during handshake */

View File

@ -223,6 +223,20 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void);
WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int);
#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_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf,
unsigned int* sz);
#endif /* WOLFSSL_DTLS */
#endif /* WOLFSSL_SESSION_EXPORT */
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int);