Merge pull request #1044 from ejohnstown/dtls-multicast

DTLS Multicast
pull/1055/head
toddouska 2017-07-24 14:20:26 -07:00 committed by GitHub
commit be61d7fca3
14 changed files with 911 additions and 83 deletions

View File

@ -349,6 +349,29 @@ AS_IF([test "x$ENABLED_SCTP" = "xyes"],
])
# DTLS-MULTICAST
AC_ARG_ENABLE([mcast],
[AS_HELP_STRING([--enable-mcast],[Enable wolfSSL DTLS multicast support (default: disabled)])],
[ENABLED_MCAST=$enableval],
[ENABLED_MCAST=no])
AM_CONDITIONAL([BUILD_MCAST], [test "x$ENABLED_MCAST" = "xyes"])
# RNG
AC_ARG_ENABLE([rng],
[AS_HELP_STRING([--enable-rng],[Enable compiling and using RNG (default: enabled)])],
[ ENABLED_RNG=$enableval ],
[ ENABLED_RNG=yes ]
)
if test "$ENABLED_RNG" = "no"
then
AM_CFLAGS="$AM_CFLAGS -DWC_NO_RNG"
fi
AM_CONDITIONAL([BUILD_RNG], [test "x$ENABLED_RNG" = "xyes"])
# OpenSSH compatibility Build
AC_ARG_ENABLE([openssh],
[AS_HELP_STRING([--enable-openssh],[Enable OpenSSH compatibility build (default: disabled)])],
@ -3532,12 +3555,21 @@ AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes" && \
AS_IF([test "x$ENABLED_SCTP" = "xyes"],
[AM_CFLAGS="-DWOLFSSL_SCTP $AM_CFLAGS"])
# SCTP requires DTLS
AS_IF([test "x$ENABLED_DTLS" = "xno" && \
test "x$ENABLED_SCTP" = "xyes"],
AS_IF([test "x$ENABLED_MCAST" = "xyes"],
[AM_CFLAGS="-DWOLFSSL_MULTICAST $AM_CFLAGS"])
# SCTP and Multicast require DTLS
AS_IF([(test "x$ENABLED_DTLS" = "xno") && \
(test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_MCAST" = "xyes")],
[AM_CFLAGS="-DWOLFSSL_DTLS $AM_CFLAGS"
ENABLED_DTLS=yes])
# Multicast requires the null cipher
AS_IF([test "x$ENABLED_NULL_CIPHER" = "xno" && \
test "x$ENABLED_MCAST" = "xyes"],
[AM_CFLAGS="-DHAVE_NULL_CIPHER $AM_CFLAGS"
ENABLED_NULL_CIPHER=yes])
################################################################################
# OPTIMIZE FLAGS
@ -3816,6 +3848,7 @@ echo " * NGINX: $ENABLED_NGINX"
echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS"
echo " * DTLS: $ENABLED_DTLS"
echo " * SCTP: $ENABLED_SCTP"
echo " * Multicast: $ENABLED_MCAST"
echo " * Old TLS Versions: $ENABLED_OLD_TLS"
echo " * SSL version 3.0: $ENABLED_SSLV3"
echo " * TLS v1.3: $ENABLED_TLS13"

View File

@ -752,8 +752,12 @@ static void Usage(void)
#ifdef WOLFSSL_EARLY_DATA
printf("-0 Early data sent to server (0-RTT handshake)\n");
#endif
#ifdef WOLFSSL_MULTICAST
printf("-3 <grpid> Multicast, grpid < 256\n");
#endif
}
THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
{
SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID;
@ -793,6 +797,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int doDTLS = 0;
int dtlsUDP = 0;
int dtlsSCTP = 0;
int doMcast = 0;
int matchName = 0;
int doPeerCheck = 1;
int nonBlocking = 0;
@ -856,6 +861,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifdef WOLFSSL_EARLY_DATA
int earlyData = 0;
#endif
#ifdef WOLFSSL_MULTICAST
byte mcastID = 0;
#endif
#ifdef HAVE_OCSP
int useOcsp = 0;
@ -905,7 +913,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
while ((ch = mygetopt(argc, argv, "?"
"ab:c:defgh:ijk:l:mnop:q:rstuv:wxyz"
"A:B:CDE:F:GHIJKL:M:NO:PQRS:TUVW:XYZ:"
"0")) != -1) {
"03:")) != -1) {
switch (ch) {
case '?' :
Usage();
@ -1231,6 +1239,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif
break;
case '3' :
#ifdef WOLFSSL_MULTICAST
doMcast = 1;
mcastID = (byte)(atoi(myoptarg) & 0xFF);
#endif
break;
default:
Usage();
exit(MY_EX_USAGE);
@ -1660,6 +1675,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
wolfSSL_CTX_allow_post_handshake_auth(ctx);
#endif
if (doMcast) {
#ifdef WOLFSSL_MULTICAST
wolfSSL_CTX_mcast_set_member_id(ctx, mcastID);
if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256") != SSL_SUCCESS) {
wolfSSL_CTX_free(ctx);
err_sys("Couldn't set multicast cipher list.");
}
#endif
}
ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
wolfSSL_CTX_free(ctx);
@ -1705,6 +1730,25 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
}
#endif
if (doMcast) {
#ifdef WOLFSSL_MULTICAST
byte pms[512]; /* pre master secret */
byte cr[32]; /* client random */
byte sr[32]; /* server random */
const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */
XMEMSET(pms, 0x23, sizeof(pms));
XMEMSET(cr, 0xA5, sizeof(cr));
XMEMSET(sr, 0x5A, sizeof(sr));
if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite)
!= SSL_SUCCESS) {
wolfSSL_CTX_free(ctx);
err_sys("unable to set mcast secret");
}
#endif
}
#ifdef HAVE_SESSION_TICKET
wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session");
#endif

View File

@ -416,6 +416,9 @@ static void Usage(void)
#ifdef WOLFSSL_EARLY_DATA
printf("-0 Early data read from client (0-RTT handshake)\n");
#endif
#ifdef WOLFSSL_MULTICAST
printf("-3 <grpid> Multicast, grpid < 256\n");
#endif
}
THREAD_RETURN CYASSL_THREAD server_test(void* args)
@ -445,6 +448,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
int doDTLS = 0;
int dtlsUDP = 0;
int dtlsSCTP = 0;
int doMcast = 0;
int needDH = 0;
int useNtruKey = 0;
int nonBlocking = 0;
@ -510,6 +514,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#ifdef WOLFSSL_SEND_HRR_COOKIE
int hrrCookie = 0;
#endif
byte mcastID = 0;
#ifdef WOLFSSL_STATIC_MEMORY
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
@ -546,6 +551,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
(void)crlFlags;
(void)readySignal;
(void)updateKeysIVs;
(void)mcastID;
#ifdef CYASSL_TIRTOS
fdOpenSession(Task_self());
@ -558,7 +564,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
while ((ch = mygetopt(argc, argv, "?"
"abc:defgijk:l:nop:q:rsuv:wx"
"A:B:C:D:E:GHIJKL:NO:PQR:S:UYZ:"
"0")) != -1) {
"03:")) != -1) {
switch (ch) {
case '?' :
Usage();
@ -795,6 +801,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#endif
break;
case '3' :
#ifdef WOLFSSL_MULTICAST
doMcast = 1;
mcastID = (byte)(atoi(myoptarg) & 0xFF);
#endif
break;
default:
Usage();
exit(MY_EX_USAGE);
@ -1119,6 +1132,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
}
#endif
if (doMcast) {
#ifdef WOLFSSL_MULTICAST
wolfSSL_CTX_mcast_set_member_id(ctx, mcastID);
if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256") != SSL_SUCCESS)
err_sys("Couldn't set multicast cipher list.");
#endif
}
ssl = SSL_new(ctx);
if (ssl == NULL)
err_sys_ex(runWithErrors, "unable to get SSL");
@ -1143,6 +1164,23 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
}
#endif
if (doMcast) {
#ifdef WOLFSSL_MULTICAST
byte pms[512];
byte cr[32];
byte sr[32];
const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */
XMEMSET(pms, 0x23, sizeof(pms));
XMEMSET(cr, 0xA5, sizeof(cr));
XMEMSET(sr, 0x5A, sizeof(sr));
if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite)
!= SSL_SUCCESS)
err_sys("unable to set mcast secret");
#endif
}
#ifndef NO_HANDSHAKE_DONE_CB
wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL);
#endif

View File

@ -534,14 +534,14 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
c32toa(keys->sequence_number_hi, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->nextEpoch, exp + idx); idx += OPAQUE16_LEN;
c16toa(keys->nextSeq_hi, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->nextSeq_lo, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->peerSeq[0].nextEpoch, exp + idx); idx += OPAQUE16_LEN;
c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->curEpoch, exp + idx); idx += OPAQUE16_LEN;
c16toa(keys->curSeq_hi, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->curSeq_lo, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->prevSeq_hi, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->prevSeq_lo, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->peerSeq[0].prevSeq_lo, 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);
@ -563,12 +563,12 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
c32toa(keys->window[i], exp + idx);
c32toa(keys->peerSeq[0].window[i], exp + idx);
idx += OPAQUE32_LEN;
}
c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
c32toa(keys->prevWindow[i], exp + idx);
c32toa(keys->peerSeq[0].prevWindow[i], exp + idx);
idx += OPAQUE32_LEN;
}
}
@ -672,14 +672,14 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
ato32(exp + idx, &keys->sequence_number_hi); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->sequence_number_lo); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->nextEpoch); idx += OPAQUE16_LEN;
ato16(exp + idx, &keys->nextSeq_hi); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->nextSeq_lo); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->peerSeq[0].nextEpoch); idx += OPAQUE16_LEN;
ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->curEpoch); idx += OPAQUE16_LEN;
ato16(exp + idx, &keys->curSeq_hi); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->curSeq_lo); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->prevSeq_hi); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->prevSeq_lo); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN;
ato16(exp + idx, &keys->dtls_expected_peer_handshake_number);
@ -708,9 +708,9 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
}
XMEMSET(keys->window, 0xFF, DTLS_SEQ_SZ);
XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ);
for (i = 0; i < wordCount; i++) {
ato32(exp + idx, &keys->window[i]);
ato32(exp + idx, &keys->peerSeq[0].window[i]);
idx += OPAQUE32_LEN;
}
idx += wordAdj;
@ -724,9 +724,9 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
}
XMEMSET(keys->prevWindow, 0xFF, DTLS_SEQ_SZ);
XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ);
for (i = 0; i < wordCount; i++) {
ato32(exp + idx, &keys->prevWindow[i]);
ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]);
idx += OPAQUE32_LEN;
}
idx += wordAdj;
@ -3725,7 +3725,10 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
byte haveAnon = 0;
byte newSSL;
byte haveRSA = 0;
(void) haveAnon; /* Squash unused var warnings */
byte haveMcast = 0;
(void)haveAnon; /* Squash unused var warnings */
(void)haveMcast;
if (!ssl || !ctx)
return BAD_FUNC_ARG;
@ -3751,6 +3754,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#ifdef HAVE_ANON
haveAnon = ctx->haveAnon;
#endif /* HAVE_ANON*/
#ifdef WOLFSSL_MULTICAST
haveMcast = ctx->haveMcast;
#endif /* WOLFSSL_MULTICAST */
/* decrement previous CTX reference count if exists.
* This should only happen if switching ctxs!*/
@ -3885,11 +3891,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
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)
/* make sure server has cert and key unless using PSK, Anon, or
* Multicast. This should be true even if just switching ssl ctx */
if (ssl->options.side == WOLFSSL_SERVER_END &&
!havePSK && !haveAnon && !haveMcast)
if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer
|| !ssl->buffers.key || !ssl->buffers.key->buffer) {
|| !ssl->buffers.key || !ssl->buffers.key->buffer) {
WOLFSSL_MSG("Server missing certificate and/or private key");
return NO_PRIVATE_KEY;
}
@ -4281,6 +4288,28 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#ifdef HAVE_SESSION_TICKET
ssl->session.ticket = ssl->session.staticTicket;
#endif
#ifdef WOLFSSL_MULTICAST
if (ctx->haveMcast) {
int i;
ssl->options.haveMcast = 1;
ssl->options.mcastID = ctx->mcastID;
/* Force the state to look like handshake has completed. */
/* Keying material is supplied externally. */
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
ssl->options.connectState = SECOND_REPLY_DONE;
ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++)
ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID;
}
#endif
return 0;
}
@ -4889,18 +4918,42 @@ static INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
{
if (order == PREV_ORDER) {
/* Previous epoch case */
seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) |
(ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF);
if (ssl->options.haveMcast) {
#ifdef WOLFSSL_MULTICAST
seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) |
(ssl->options.mcastID << 8) |
(ssl->keys.dtls_prev_sequence_number_hi & 0xFF);
#endif
}
else
seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) |
(ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF);
seq[1] = ssl->keys.dtls_prev_sequence_number_lo;
}
else if (order == PEER_ORDER) {
seq[0] = (ssl->keys.curEpoch << 16) |
(ssl->keys.curSeq_hi & 0xFFFF);
if (ssl->options.haveMcast) {
#ifdef WOLFSSL_MULTICAST
seq[0] = (ssl->keys.curEpoch << 16) |
(ssl->keys.curPeerId << 8) |
(ssl->keys.curSeq_hi & 0xFF);
#endif
}
else
seq[0] = (ssl->keys.curEpoch << 16) |
(ssl->keys.curSeq_hi & 0xFFFF);
seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */
}
else {
seq[0] = (ssl->keys.dtls_epoch << 16) |
(ssl->keys.dtls_sequence_number_hi & 0xFFFF);
if (ssl->options.haveMcast) {
#ifdef WOLFSSL_MULTICAST
seq[0] = (ssl->keys.dtls_epoch << 16) |
(ssl->options.mcastID << 8) |
(ssl->keys.dtls_sequence_number_hi & 0xFF);
#endif
}
else
seq[0] = (ssl->keys.dtls_epoch << 16) |
(ssl->keys.dtls_sequence_number_hi & 0xFFFF);
seq[1] = ssl->keys.dtls_sequence_number_lo;
}
}
@ -6200,7 +6253,14 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
*inOutIdx += ENUM_LEN + VERSION_SZ;
ato16(input + *inOutIdx, &ssl->keys.curEpoch);
*inOutIdx += OPAQUE16_LEN;
ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
if (ssl->options.haveMcast) {
#ifdef WOLFSSL_MULTICAST
ssl->keys.curPeerId = input[*inOutIdx];
ssl->keys.curSeq_hi = input[*inOutIdx+1];
#endif
}
else
ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
*inOutIdx += OPAQUE16_LEN;
ato32(input + *inOutIdx, &ssl->keys.curSeq_lo);
*inOutIdx += OPAQUE32_LEN; /* advance past rest of seq */
@ -7060,6 +7120,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
return 1;
break;
#endif
#ifdef WOLFSSL_MULTICAST
case WDM_WITH_NULL_SHA256 :
break;
#endif
default:
WOLFSSL_MSG("Unsupported cipher suite, CipherRequires");
@ -9552,16 +9616,41 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl)
word16 cur_hi, next_hi;
word32 cur_lo, next_lo, diff;
int curLT;
WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL;
if (ssl->keys.curEpoch == ssl->keys.nextEpoch) {
next_hi = ssl->keys.nextSeq_hi;
next_lo = ssl->keys.nextSeq_lo;
window = ssl->keys.window;
if (!ssl->options.haveMcast)
peerSeq = ssl->keys.peerSeq;
else {
#ifdef WOLFSSL_MULTICAST
WOLFSSL_DTLS_PEERSEQ* p;
int i;
for (i = 0, p = ssl->keys.peerSeq;
i < WOLFSSL_DTLS_PEERSEQ_SZ;
i++, p++) {
if (p->peerId == ssl->keys.curPeerId) {
peerSeq = p;
break;
}
}
if (peerSeq == NULL) {
WOLFSSL_MSG("Couldn't find that peer ID to check window.");
return 0;
}
#endif
}
else if (ssl->keys.curEpoch == ssl->keys.nextEpoch - 1) {
next_hi = ssl->keys.prevSeq_hi;
next_lo = ssl->keys.prevSeq_lo;
window = ssl->keys.prevWindow;
if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
next_hi = peerSeq->nextSeq_hi;
next_lo = peerSeq->nextSeq_lo;
window = peerSeq->window;
}
else if (ssl->keys.curEpoch == peerSeq->nextEpoch - 1) {
next_hi = peerSeq->prevSeq_hi;
next_lo = peerSeq->prevSeq_lo;
window = peerSeq->prevWindow;
}
else {
return 0;
@ -9595,10 +9684,12 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl)
WOLFSSL_MSG("Current record sequence number from the past.");
return 0;
}
#ifndef WOLFSSL_DTLS_ALLOW_FUTURE
else if (!curLT && (diff > DTLS_SEQ_BITS)) {
WOLFSSL_MSG("Rejecting message too far into the future.");
return 0;
}
#endif
else if (curLT) {
word32 idx = diff / DTLS_WORD_BITS;
word32 newDiff = diff % DTLS_WORD_BITS;
@ -9619,6 +9710,24 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl)
}
#ifdef WOLFSSL_MULTICAST
static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
word32 second, word32 max)
{
word32 newCur = 0;
if (cur < first)
newCur = first;
else if (cur < second)
newCur = second;
else if (cur < max)
newCur = max;
return newCur;
}
#endif /* WOLFSSL_MULTICAST */
static INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
{
word32* window;
@ -9627,21 +9736,63 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
int curLT;
word32 cur_lo, diff;
word16 cur_hi;
if (ssl->keys.curEpoch == ssl->keys.nextEpoch) {
next_hi = &ssl->keys.nextSeq_hi;
next_lo = &ssl->keys.nextSeq_lo;
window = ssl->keys.window;
}
else {
next_hi = &ssl->keys.prevSeq_hi;
next_lo = &ssl->keys.prevSeq_lo;
window = ssl->keys.prevWindow;
}
WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
cur_hi = ssl->keys.curSeq_hi;
cur_lo = ssl->keys.curSeq_lo;
#ifdef WOLFSSL_MULTICAST
if (ssl->options.haveMcast) {
WOLFSSL_DTLS_PEERSEQ* p;
int i;
peerSeq = NULL;
for (i = 0, p = ssl->keys.peerSeq;
i < WOLFSSL_DTLS_PEERSEQ_SZ;
i++, p++) {
if (p->peerId == ssl->keys.curPeerId) {
peerSeq = p;
break;
}
}
if (peerSeq == NULL) {
WOLFSSL_MSG("Couldn't find that peer ID to update window.");
return 0;
}
if (p->highwaterMark && cur_lo >= p->highwaterMark) {
int cbError = 0;
if (ssl->ctx->mcastHwCb)
cbError = ssl->ctx->mcastHwCb(p->peerId,
ssl->ctx->mcastMaxSeq,
cur_lo, ssl->mcastHwCbCtx);
if (cbError) {
WOLFSSL_MSG("Multicast highwater callback returned an error.");
return MCAST_HIGHWATER_CB_E;
}
p->highwaterMark = UpdateHighwaterMark(cur_lo,
ssl->ctx->mcastFirstSeq,
ssl->ctx->mcastSecondSeq,
ssl->ctx->mcastMaxSeq);
}
}
#endif
if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
next_hi = &peerSeq->nextSeq_hi;
next_lo = &peerSeq->nextSeq_lo;
window = peerSeq->window;
}
else {
next_hi = &peerSeq->prevSeq_hi;
next_lo = &peerSeq->prevSeq_lo;
window = peerSeq->prevWindow;
}
if (cur_hi == *next_hi) {
curLT = cur_lo < *next_lo;
diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo;
@ -10676,6 +10827,10 @@ static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
if (ret == VERIFY_MAC_ERROR) {
if (!ssl->options.dtls)
SendAlert(ssl, alert_fatal, bad_record_mac);
#ifdef WOLFSSL_DTLS_DROP_STATS
ssl->macDropCount++;
#endif /* WOLFSSL_DTLS_DROP_STATS */
}
return ret;
@ -11401,6 +11556,9 @@ int ProcessReply(WOLFSSL* ssl)
ssl->options.processReply = doProcessInit;
ssl->buffers.inputBuffer.length = 0;
ssl->buffers.inputBuffer.idx = 0;
#ifdef WOLFSSL_DTLS_DROP_STATS
ssl->replayDropCount++;
#endif /* WOLFSSL_DTLS_DROP_STATS */
if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) {
ret = DtlsMsgPoolSend(ssl, 0);
@ -11539,6 +11697,9 @@ int ProcessReply(WOLFSSL* ssl)
if (ret < 0) {
WOLFSSL_MSG("VerifyMac failed");
WOLFSSL_ERROR(ret);
#ifdef WOLFSSL_DTLS_DROP_STATS
ssl->macDropCount++;
#endif /* WOLFSSL_DTLS_DROP_STATS */
return DECRYPT_ERROR;
}
}
@ -11670,20 +11831,33 @@ int ProcessReply(WOLFSSL* ssl)
ssl->keys.encryptionOn = 1;
/* setup decrypt keys for following messages */
/* XXX This might not be what we want to do when
* receiving a CCS with multicast. We update the
* key when the application updates them. */
if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
return ret;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
#ifdef WOLFSSL_MULTICAST
if (ssl->options.haveMcast) {
peerSeq += ssl->keys.curPeerId;
peerSeq->highwaterMark = UpdateHighwaterMark(0,
ssl->ctx->mcastFirstSeq,
ssl->ctx->mcastSecondSeq,
ssl->ctx->mcastMaxSeq);
}
#endif
DtlsMsgPoolReset(ssl);
ssl->keys.prevSeq_lo = ssl->keys.nextSeq_lo;
ssl->keys.prevSeq_hi = ssl->keys.nextSeq_hi;
XMEMCPY(ssl->keys.prevWindow, ssl->keys.window,
peerSeq->nextEpoch++;
peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
peerSeq->nextSeq_lo = 0;
peerSeq->nextSeq_hi = 0;
XMEMCPY(peerSeq->prevWindow, peerSeq->window,
DTLS_SEQ_SZ);
ssl->keys.nextEpoch++;
ssl->keys.nextSeq_lo = 0;
ssl->keys.nextSeq_hi = 0;
XMEMSET(ssl->keys.window, 0, DTLS_SEQ_SZ);
XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
}
#endif
@ -14064,6 +14238,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case HRR_COOKIE_ERROR:
return "Cookie does not match one sent in HelloRetryRequest";
case MCAST_HIGHWATER_CB_E:
return "Multicast highwater callback returned error";
default :
return "unknown error number";
}
@ -14540,6 +14717,9 @@ static const char* const cipher_names[] =
"TLS13-AES128-CCM-8-SHA256",
#endif
#ifdef BUILD_WDM_WITH_NULL_SHA256
"WDM-NULL-SHA256",
#endif
};
@ -15007,6 +15187,9 @@ static int cipher_name_idx[] =
TLS_AES_128_CCM_8_SHA256,
#endif
#ifdef BUILD_WDM_WITH_NULL_SHA256
WDM_WITH_NULL_SHA256,
#endif
};
@ -15495,6 +15678,10 @@ const char* wolfSSL_get_cipher_name_from_suite(const unsigned char cipherSuite,
#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
case TLS_DH_anon_WITH_AES_128_CBC_SHA :
return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
#endif
#ifdef BUILD_WDM_WITH_NULL_SHA256
case WDM_WITH_NULL_SHA256 :
return "WDM_WITH_NULL_SHA256";
#endif
default:
return "NONE";

View File

@ -296,7 +296,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
if (dtlsCtx->peer.sz > 0
&& peerSz != (XSOCKLENT)dtlsCtx->peer.sz
&& XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
WOLFSSL_MSG("\tIgnored packet from invalid peer");
WOLFSSL_MSG(" Ignored packet from invalid peer");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
}
@ -354,6 +354,61 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
}
#ifdef WOLFSSL_MULTICAST
/* The alternate receive embedded callback for Multicast
* return : nb bytes read, or error
*/
int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
int recvd;
int err;
int sd = dtlsCtx->rfd;
WOLFSSL_ENTER("EmbedReceiveFromMcast()");
recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL);
recvd = TranslateReturnCode(recvd, sd);
if (recvd < 0) {
err = LastError();
WOLFSSL_MSG("Embed Receive From error");
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
if (wolfSSL_get_using_nonblock(ssl)) {
WOLFSSL_MSG("\tWould block");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
else {
WOLFSSL_MSG("\tSocket timeout");
return WOLFSSL_CBIO_ERR_TIMEOUT;
}
}
else if (err == SOCKET_ECONNRESET) {
WOLFSSL_MSG("\tConnection reset");
return WOLFSSL_CBIO_ERR_CONN_RST;
}
else if (err == SOCKET_EINTR) {
WOLFSSL_MSG("\tSocket interrupted");
return WOLFSSL_CBIO_ERR_ISR;
}
else if (err == SOCKET_ECONNREFUSED) {
WOLFSSL_MSG("\tConnection refused");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
else {
WOLFSSL_MSG("\tGeneral error");
return WOLFSSL_CBIO_ERR_GENERAL;
}
}
return recvd;
}
#endif /* WOLFSSL_MULTICAST */
/* The DTLS Generate Cookie callback
* return : number of bytes copied into buf, or error
*/
@ -362,7 +417,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
int sd = ssl->wfd;
SOCKADDR_S peer;
XSOCKLENT peerSz = sizeof(peer);
byte digest[SHA_DIGEST_SIZE];
byte digest[SHA256_DIGEST_SIZE];
int ret = 0;
(void)ctx;
@ -373,12 +428,12 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
return GEN_COOKIE_E;
}
ret = wc_ShaHash((byte*)&peer, peerSz, digest);
ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
if (ret != 0)
return ret;
if (sz > SHA_DIGEST_SIZE)
sz = SHA_DIGEST_SIZE;
if (sz > SHA256_DIGEST_SIZE)
sz = SHA256_DIGEST_SIZE;
XMEMCPY(buf, digest, sz);
return sz;

View File

@ -2083,6 +2083,19 @@ int SetCipherSpecs(WOLFSSL* ssl)
break;
#endif
#ifdef BUILD_WDM_WITH_NULL_SHA256
case WDM_WITH_NULL_SHA256 :
ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = no_kea;
ssl->specs.sig_algo = anonymous_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
break;
#endif
default:
WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs");
return UNSUPPORTED_SUITE;
@ -3043,6 +3056,35 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
}
#endif /* HAVE_SECURE_RENEGOTIATION */
#ifdef WOLFSSL_MULTICAST
if (ssl->options.haveMcast) {
/* Use the same keys for encrypt and decrypt. */
if (ssl->specs.cipher_type != aead) {
sz = ssl->specs.hash_size;
XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
i += sz;
}
sz = ssl->specs.key_size;
XMEMCPY(keys->client_write_key, &keyData[i], sz);
XMEMCPY(keys->server_write_key, &keyData[i], sz);
i += sz;
sz = ssl->specs.iv_size;
XMEMCPY(keys->client_write_IV, &keyData[i], sz);
XMEMCPY(keys->server_write_IV, &keyData[i], sz);
#ifdef HAVE_AEAD
if (ssl->specs.cipher_type == aead) {
/* Initialize the AES-GCM/CCM explicit IV to a zero. */
XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ);
}
#endif /* HAVE_AEAD */
return 0;
}
#endif /* WOLFSSL_MULTICAST */
if (ssl->specs.cipher_type != aead) {
sz = ssl->specs.hash_size;
if (side & PROVISION_CLIENT) {

298
src/ssl.c
View File

@ -843,6 +843,276 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */
#ifdef WOLFSSL_DTLS_DROP_STATS
int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl,
word32* macDropCount, word32* replayDropCount)
{
int ret;
WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()");
if (ssl == NULL)
ret = BAD_FUNC_ARG;
else {
ret = SSL_SUCCESS;
if (macDropCount != NULL)
*macDropCount = ssl->macDropCount;
if (replayDropCount != NULL)
*replayDropCount = ssl->replayDropCount;
}
WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret);
return ret;
}
#endif /* WOLFSSL_DTLS_DROP_STATS */
#if defined(WOLFSSL_MULTICAST)
int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id)
{
int ret = 0;
WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()");
if (ctx == NULL || id > 255)
ret = BAD_FUNC_ARG;
if (ret == 0) {
ctx->haveEMS = 0;
ctx->haveMcast = 1;
ctx->mcastID = id;
#ifndef WOLFSSL_USER_IO
ctx->CBIORecv = EmbedReceiveFromMcast;
#endif /* WOLFSSL_USER_IO */
}
if (ret == 0)
ret = SSL_SUCCESS;
WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret);
return ret;
}
int wolfSSL_mcast_get_max_peers(void)
{
return WOLFSSL_MULTICAST_PEERS;
}
#ifdef WOLFSSL_DTLS
static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
word32 second, word32 max)
{
word32 newCur = 0;
if (cur < first)
newCur = first;
else if (cur < second)
newCur = second;
else if (cur < max)
newCur = max;
return newCur;
}
#endif /* WOLFSSL_DTLS */
int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch,
const byte* preMasterSecret, word32 preMasterSz,
const byte* clientRandom, const byte* serverRandom,
const byte* suite)
{
int ret = 0;
WOLFSSL_ENTER("wolfSSL_set_secret()");
if (ssl == NULL || preMasterSecret == NULL ||
preMasterSz == 0 || preMasterSz > ENCRYPT_LEN ||
clientRandom == NULL || serverRandom == NULL || suite == NULL) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz);
ssl->arrays->preMasterSz = preMasterSz;
XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN);
XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN);
ssl->options.cipherSuite0 = suite[0];
ssl->options.cipherSuite = suite[1];
ret = SetCipherSpecs(ssl);
}
if (ret == 0)
ret = MakeTlsMasterSecret(ssl);
if (ret == 0) {
ssl->keys.encryptionOn = 1;
ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
}
if (ret == 0) {
if (ssl->options.dtls) {
#ifdef WOLFSSL_DTLS
WOLFSSL_DTLS_PEERSEQ* peerSeq;
int i;
ssl->keys.dtls_epoch = epoch;
for (i = 0, peerSeq = ssl->keys.peerSeq;
i < WOLFSSL_DTLS_PEERSEQ_SZ;
i++, peerSeq++) {
peerSeq->nextEpoch = epoch;
peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
peerSeq->nextSeq_lo = 0;
peerSeq->nextSeq_hi = 0;
XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ);
XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
peerSeq->highwaterMark = UpdateHighwaterMark(0,
ssl->ctx->mcastFirstSeq,
ssl->ctx->mcastSecondSeq,
ssl->ctx->mcastMaxSeq);
}
#else
(void)epoch;
#endif
}
FreeHandshakeResources(ssl);
ret = SSL_SUCCESS;
}
else {
if (ssl)
ssl->error = ret;
ret = SSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_set_secret()", ret);
return ret;
}
#ifdef WOLFSSL_DTLS
int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove)
{
WOLFSSL_DTLS_PEERSEQ* p = NULL;
int ret = SSL_SUCCESS;
int i;
WOLFSSL_ENTER("wolfSSL_mcast_peer_add()");
if (ssl == NULL || peerId > 255)
return BAD_FUNC_ARG;
if (!remove) {
/* Make sure it isn't already present, while keeping the first
* open spot. */
for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID)
p = &ssl->keys.peerSeq[i];
if (ssl->keys.peerSeq[i].peerId == peerId) {
WOLFSSL_MSG("Peer ID already in multicast peer list.");
p = NULL;
}
}
if (p != NULL) {
XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ));
p->peerId = peerId;
p->highwaterMark = UpdateHighwaterMark(0,
ssl->ctx->mcastFirstSeq,
ssl->ctx->mcastSecondSeq,
ssl->ctx->mcastMaxSeq);
}
else {
WOLFSSL_MSG("No room in peer list.");
ret = -1;
}
}
else {
for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
if (ssl->keys.peerSeq[i].peerId == peerId)
p = &ssl->keys.peerSeq[i];
}
if (p != NULL) {
p->peerId = INVALID_PEER_ID;
}
else {
WOLFSSL_MSG("Peer not found in list.");
}
}
WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret);
return ret;
}
/* If peerId is in the list of peers and its last sequence number is non-zero,
* return 1, otherwise return 0. */
int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId)
{
int known = 0;
int i;
WOLFSSL_ENTER("wolfSSL_mcast_peer_known()");
if (ssl == NULL || peerId > 255) {
return BAD_FUNC_ARG;
}
for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
if (ssl->keys.peerSeq[i].peerId == peerId) {
if (ssl->keys.peerSeq[i].nextSeq_hi ||
ssl->keys.peerSeq[i].nextSeq_lo) {
known = 1;
}
break;
}
}
WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known);
return known;
}
int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq,
word32 first, word32 second,
CallbackMcastHighwater cb)
{
if (ctx == NULL || (second && first > second) ||
first > maxSeq || second > maxSeq || cb == NULL) {
return BAD_FUNC_ARG;
}
ctx->mcastHwCb = cb;
ctx->mcastFirstSeq = first;
ctx->mcastSecondSeq = second;
ctx->mcastMaxSeq = maxSeq;
return SSL_SUCCESS;
}
int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx)
{
if (ssl == NULL || ctx == NULL)
return BAD_FUNC_ARG;
ssl->mcastHwCbCtx = ctx;
return SSL_SUCCESS;
}
#endif /* WOLFSSL_DTLS */
#endif /* WOLFSSL_MULTICAST */
#endif /* WOLFSSL_LEANPSK */
@ -1452,6 +1722,25 @@ int wolfSSL_read(WOLFSSL* ssl, void* data, int sz)
}
#ifdef WOLFSSL_MULTICAST
int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
{
int ret = 0;
WOLFSSL_ENTER("wolfSSL_mcast_read()");
if (ssl == NULL)
return BAD_FUNC_ARG;
ret = wolfSSL_read_internal(ssl, data, sz, FALSE);
if (ssl->options.dtls && ssl->options.haveMcast && id != NULL)
*id = ssl->keys.curPeerId;
return ret;
}
#endif /* WOLFSSL_MULTICAST */
#ifdef WOLFSSL_ASYNC_CRYPT
/* let's use async hardware, SSL_SUCCESS on ok */
@ -8643,12 +8932,12 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
{
word16 havePSK = 0;
word16 haveAnon = 0;
word16 haveMcast = 0;
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3)
return wolfSSL_accept_TLSv13(ssl);
#endif
WOLFSSL_ENTER("SSL_accept()");
#ifdef HAVE_ERRNO_H
@ -8665,6 +8954,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#endif
(void)haveAnon;
#ifdef WOLFSSL_MULTICAST
haveMcast = ssl->options.haveMcast;
#endif
(void)haveMcast;
if (ssl->options.side != WOLFSSL_SERVER_END) {
WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
return SSL_FATAL_ERROR;
@ -8672,7 +8966,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#ifndef NO_CERTS
/* in case used set_accept_state after init */
if (!havePSK && !haveAnon &&
if (!havePSK && !haveAnon && !haveMcast &&
(!ssl->buffers.certificate ||
!ssl->buffers.certificate->buffer ||
!ssl->buffers.key ||

View File

@ -2344,6 +2344,49 @@ static int test_wolfSSL_UseOCSPStaplingV2 (void)
} /*END test_wolfSSL_UseOCSPStaplingV2*/
/*----------------------------------------------------------------------------*
| Multicast Tests
*----------------------------------------------------------------------------*/
static void test_wolfSSL_mcast(void)
{
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST)
WOLFSSL_CTX* ctx;
WOLFSSL* ssl;
int result;
byte preMasterSecret[512];
byte clientRandom[32];
byte serverRandom[32];
byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */
byte buf[256];
word16 newId;
ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method());
AssertNotNull(ctx);
result = wolfSSL_CTX_mcast_set_member_id(ctx, 0);
AssertIntEQ(result, SSL_SUCCESS);
ssl = wolfSSL_new(ctx);
AssertNotNull(ssl);
XMEMSET(preMasterSecret, 0x23, sizeof(preMasterSecret));
XMEMSET(clientRandom, 0xA5, sizeof(clientRandom));
XMEMSET(serverRandom, 0x5A, sizeof(serverRandom));
result = wolfSSL_set_secret(ssl, 23,
preMasterSecret, sizeof(preMasterSecret),
clientRandom, serverRandom, suite);
AssertIntEQ(result, SSL_SUCCESS);
result = wolfSSL_mcast_read(ssl, &newId, buf, sizeof(buf));
AssertIntLE(result, 0);
AssertIntLE(newId, 100);
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST */
}
/*----------------------------------------------------------------------------*
| Wolfcrypt
*----------------------------------------------------------------------------*/
@ -9707,6 +9750,9 @@ void ApiTest(void)
AssertIntEQ(test_wolfSSL_UseOCSPStapling(), SSL_SUCCESS);
AssertIntEQ(test_wolfSSL_UseOCSPStaplingV2(), SSL_SUCCESS);
/* Multicast */
test_wolfSSL_mcast();
/* compatibility tests */
test_wolfSSL_DES();
test_wolfSSL_certs();

View File

@ -161,6 +161,7 @@ enum wolfSSL_ErrorCodes {
BAD_BINDER = -423, /* Binder does not match */
EXT_NOT_ALLOWED = -424, /* Extension not allowed in msg */
INVALID_PARAMETER = -425, /* Security parameter invalid */
MCAST_HIGHWATER_CB_E = -426, /* Multicast highwater cb err */
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
/* begin negotiation parameter errors */

View File

@ -657,6 +657,12 @@ typedef byte word24[3];
#endif
#endif
#ifdef WOLFSSL_MULTICAST
#if defined(HAVE_NULL_CIPHER) && !defined(NO_SHA256)
#define BUILD_WDM_WITH_NULL_SHA256
#endif
#endif
#if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \
defined(BUILD_SSL_RSA_WITH_RC4_128_MD5)
#define BUILD_ARC4
@ -794,6 +800,7 @@ enum {
TLS_RSA_WITH_HC_128_MD5 = 0xFB,
TLS_RSA_WITH_HC_128_SHA = 0xFC,
TLS_RSA_WITH_RABBIT_SHA = 0xFD,
WDM_WITH_NULL_SHA256 = 0xFE, /* wolfSSL DTLS Multicast */
/* wolfSSL extension - Blake2b 256 */
TLS_RSA_WITH_AES_128_CBC_B2B256 = 0xF8,
@ -907,6 +914,21 @@ enum {
#define DTLS_SEQ_BITS (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS)
#define DTLS_SEQ_SZ (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS)
#ifndef WOLFSSL_MULTICAST
#define WOLFSSL_DTLS_PEERSEQ_SZ 1
#else
#ifndef WOLFSSL_MULTICAST_PEERS
/* max allowed multicast group peers */
#define WOLFSSL_MULTICAST_PEERS 100
#endif
#define WOLFSSL_DTLS_PEERSEQ_SZ WOLFSSL_MULTICAST_PEERS
#endif /* WOLFSSL_MULTICAST */
#ifndef WOLFSSL_MAX_MTU
#define WOLFSSL_MAX_MTU 1500
#endif /* WOLFSSL_MAX_MTU */
enum Misc {
ECC_BYTE = 0xC0, /* ECC first cipher suite byte */
@ -952,7 +974,7 @@ enum Misc {
/* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max
digest sz + BLOC_SZ (iv) + pad byte (1) */
MAX_COMP_EXTRA = 1024, /* max compression extra */
MAX_MTU = 1500, /* max expected MTU */
MAX_MTU = WOLFSSL_MAX_MTU, /* max expected MTU */
MAX_UDP_SIZE = 8192 - 100, /* was MAX_MTU - 100 */
MAX_DH_SZ = 1036, /* 4096 p, pub, g + 2 byte size for each */
MAX_STR_VERSION = 8, /* string rep of protocol version */
@ -1150,6 +1172,8 @@ enum Misc {
NO_COPY = 0, /* should we copy static buffer for write */
COPY = 1, /* should we copy static buffer for write */
INVALID_PEER_ID = 0xFFFF, /* Initialize value for peer ID. */
PREV_ORDER = -1, /* Sequence number is in previous epoch. */
PEER_ORDER = 1, /* Peer sequence number for verify. */
CUR_ORDER = 0 /* Current sequence number. */
@ -1716,6 +1740,25 @@ typedef struct WOLFSSL_DTLS_CTX {
} WOLFSSL_DTLS_CTX;
typedef struct WOLFSSL_DTLS_PEERSEQ {
word32 window[WOLFSSL_DTLS_WINDOW_WORDS];
/* Sliding window for current epoch */
word16 nextEpoch; /* Expected epoch in next record */
word16 nextSeq_hi; /* Expected sequence in next record */
word32 nextSeq_lo;
word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS];
/* Sliding window for old epoch */
word32 prevSeq_lo;
word16 prevSeq_hi; /* Next sequence in allowed old epoch */
#ifdef WOLFSSL_MULTICAST
word16 peerId;
word32 highwaterMark;
#endif
} WOLFSSL_DTLS_PEERSEQ;
#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */
/* keys and secrets
@ -1739,20 +1782,13 @@ typedef struct Keys {
word32 sequence_number_lo;
#ifdef WOLFSSL_DTLS
word32 window[WOLFSSL_DTLS_WINDOW_WORDS];
/* Sliding window for current epoch */
word16 nextEpoch; /* Expected epoch in next record */
word16 nextSeq_hi; /* Expected sequence in next record */
word32 nextSeq_lo;
word16 curEpoch; /* Received epoch in current record */
word16 curSeq_hi; /* Received sequence in current record */
word32 curSeq_lo;
word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS];
/* Sliding window for old epoch */
word16 prevSeq_hi; /* Next sequence in allowed old epoch */
word32 prevSeq_lo;
#ifdef WOLFSSL_MULTICAST
byte curPeerId; /* Received peer group ID in current record */
#endif
WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_DTLS_PEERSEQ_SZ];
word16 dtls_peer_handshake_number;
word16 dtls_expected_peer_handshake_number;
@ -2232,6 +2268,10 @@ struct WOLFSSL_CTX {
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
byte postHandshakeAuth:1; /* Post-handshake auth supported. */
#endif
#ifdef WOLFSSL_MULTICAST
byte haveMcast; /* multicast requested */
byte mcastID; /* multicast group ID */
#endif
#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
byte dtlsSctp; /* DTLS-over-SCTP mode */
word16 dtlsMtuSz; /* DTLS MTU size */
@ -2299,6 +2339,12 @@ struct WOLFSSL_CTX {
CallbackSniRecv sniRecvCb;
void* sniRecvCbArg;
#endif
#if defined(WOLFSSL_MULTICAST) && defined(WOLFSSL_DTLS)
CallbackMcastHighwater mcastHwCb; /* Sequence number highwater callback */
word32 mcastFirstSeq; /* first trigger level */
word32 mcastSecondSeq; /* second tigger level */
word32 mcastMaxSeq; /* max level */
#endif
#ifdef HAVE_OCSP
WOLFSSL_OCSP ocsp;
#endif
@ -2813,6 +2859,7 @@ typedef struct Options {
word16 saveArrays:1; /* save array Memory for user get keys
or psk */
word16 weOwnRng:1; /* will be true unless CTX owns */
word16 haveEMS:1; /* using extended master secret */
#ifdef HAVE_POLY1305
word16 oldPoly:1; /* set when to use old rfc way of poly*/
#endif
@ -2829,11 +2876,11 @@ typedef struct Options {
#endif
#ifdef WOLFSSL_DTLS
word16 dtlsHsRetain:1; /* DTLS retaining HS data */
word16 haveMcast:1; /* using multicast ? */
#ifdef WOLFSSL_SCTP
word16 dtlsSctp:1; /* DTLS-over-SCTP mode */
#endif
#endif
word16 haveEMS:1; /* using extended master secret */
#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES)
word16 userCurves:1; /* indicates user called wolfSSL_UseSupportedCurve */
#endif
@ -2860,6 +2907,9 @@ typedef struct Options {
byte acceptState; /* nonblocking resume */
byte asyncState; /* sub-state for enum asyncState */
byte buildMsgState; /* sub-state for enum buildMsgState */
#ifdef WOLFSSL_MULTICAST
word16 mcastID; /* Multicast group ID */
#endif
#ifndef NO_DH
word16 minDhKeySz; /* minimum DH key size */
word16 dhKeySz; /* actual DH key size */
@ -3296,7 +3346,14 @@ struct WOLFSSL {
#ifdef WOLFSSL_SCTP
word16 dtlsMtuSz;
#endif /* WOLFSSL_SCTP */
#endif
#ifdef WOLFSSL_MULTICAST
void* mcastHwCbCtx; /* Multicast highwater callback ctx */
#endif /* WOLFSSL_MULTICAST */
#ifdef WOLFSSL_DTLS_DROP_STATS
word32 macDropCount;
word32 replayDropCount;
#endif /* WOLFSSL_DTLS_DROP_STATS */
#endif /* WOLFSSL_DTLS */
#ifdef WOLFSSL_CALLBACKS
HandShakeInfo handShakeInfo; /* info saved during handshake */
TimeoutInfo timeoutInfo; /* info saved during handshake */

View File

@ -298,6 +298,10 @@ WOLFSSL_API int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags);
WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx);
WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf,
int sz, void*);
#ifdef WOLFSSL_MULTICAST
WOLFSSL_API int EmbedReceiveFromMcast(WOLFSSL* ssl,
char* buf, int sz, void*);
#endif /* WOLFSSL_MULTICAST */
#ifdef WOLFSSL_SESSION_EXPORT
WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
unsigned short* port, int* fam);

View File

@ -509,6 +509,27 @@ WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*);
WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short);
WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short);
WOLFSSL_API int wolfSSL_dtls_get_drop_stats(WOLFSSL*,
unsigned int*, unsigned int*);
WOLFSSL_API int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short);
WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short,
const unsigned char*, unsigned int,
const unsigned char*, const unsigned char*,
const unsigned char*);
WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int);
WOLFSSL_API int wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int);
WOLFSSL_API int wolfSSL_mcast_peer_known(WOLFSSL*, unsigned short);
WOLFSSL_API int wolfSSL_mcast_get_max_peers(void);
typedef int (*CallbackMcastHighwater)(unsigned short peerId,
unsigned int maxSeq,
unsigned int curSeq, void* ctx);
WOLFSSL_API int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX*,
unsigned int,
unsigned int,
unsigned int,
CallbackMcastHighwater);
WOLFSSL_API int wolfSSL_mcast_set_highwater_ctx(WOLFSSL*, void*);
WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err);
WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*);
WOLFSSL_API void wolfSSL_ERR_error_string_n(unsigned long e, char* buf,

View File

@ -153,7 +153,7 @@
#include <wolfssl/wolfcrypt/visibility.h>
#ifdef WOLFSSL_USER_SETTINGS
#include <user_settings.h>
#include "user_settings.h"
#endif
@ -174,7 +174,10 @@
#endif
#ifdef HAVE_NETX
#include "nx_api.h"
#ifdef NEED_THREADX_TYPES
#include <types.h>
#endif
#include <nx_api.h>
#endif
#if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */

View File

@ -49,7 +49,10 @@
#endif
#elif defined(THREADX)
#ifndef SINGLE_THREADED
#include "tx_api.h"
#ifdef NEED_THREADX_TYPES
#include <types.h>
#endif
#include <tx_api.h>
#endif
#elif defined(MICRIUM)
/* do nothing, just don't pick Unix */