diff --git a/src/internal.c b/src/internal.c index 2fdb3864a..72bfe1a53 100755 --- a/src/internal.c +++ b/src/internal.c @@ -9706,6 +9706,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; @@ -9716,6 +9734,9 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) word16 cur_hi; WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; + cur_hi = ssl->keys.curSeq_hi; + cur_lo = ssl->keys.curSeq_lo; + if (!ssl->options.haveMcast) peerSeq = ssl->keys.peerSeq; else { @@ -9738,6 +9759,24 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) 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 } @@ -9752,9 +9791,6 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) window = peerSeq->prevWindow; } - cur_hi = ssl->keys.curSeq_hi; - cur_lo = ssl->keys.curSeq_lo; - if (cur_hi == *next_hi) { curLT = cur_lo < *next_lo; diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo; @@ -11793,8 +11829,13 @@ int ProcessReply(WOLFSSL* ssl) if (ssl->options.dtls) { WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; #ifdef WOLFSSL_MULTICAST - if (ssl->options.haveMcast) + if (ssl->options.haveMcast) { peerSeq += ssl->keys.curPeerId; + peerSeq->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } #endif DtlsMsgPoolReset(ssl); peerSeq->nextEpoch++; @@ -14185,6 +14226,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"; } diff --git a/src/ssl.c b/src/ssl.c index 2aa775375..756d0aaf0 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -868,6 +868,24 @@ int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id) } +#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, unsigned short epoch, const byte* preMasterSecret, word32 preMasterSz, const byte* clientRandom, const byte* serverRandom, @@ -921,6 +939,10 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, 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); } #endif } @@ -936,6 +958,8 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, } +#ifdef WOLFSSL_DTLS + int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) { WOLFSSL_DTLS_PEERSEQ* p = NULL; @@ -961,6 +985,10 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) 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."); @@ -985,6 +1013,38 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) return ret; } + +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 */ diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 09d843699..f827d3acf 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -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 */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e14b2ec63..3459212f1 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1748,7 +1748,10 @@ typedef struct WOLFSSL_DTLS_PEERSEQ { word32 prevSeq_lo; word16 prevSeq_hi; /* Next sequence in allowed old epoch */ +#ifdef WOLFSSL_MULTICAST word16 peerId; + word32 highwaterMark; +#endif } WOLFSSL_DTLS_PEERSEQ; @@ -2332,6 +2335,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 @@ -3335,7 +3344,10 @@ struct WOLFSSL { #ifdef WOLFSSL_SCTP word16 dtlsMtuSz; #endif /* WOLFSSL_SCTP */ -#endif +#ifdef WOLFSSL_MULTICAST + void* mcastHwCbCtx; /* Multicast highwater callback ctx */ +#endif /* WOLFSSL_MULTICAST */ +#endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS HandShakeInfo handShakeInfo; /* info saved during handshake */ TimeoutInfo timeoutInfo; /* info saved during handshake */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 1026129d7..1ae8c13be 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -516,6 +516,15 @@ WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, 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); +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*);