Skip to content

Commit cb138b2

Browse files
authored
Merge pull request #11163 from kareem-wolfssl/vanessa
Fix a few sniffer issues. Document DES function size requirements.
2 parents ac45965 + 54e4149 commit cb138b2

2 files changed

Lines changed: 69 additions & 16 deletions

File tree

src/sniffer.c

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -478,8 +478,10 @@ typedef struct Flags {
478478

479479
/* Out of Order FIN capture */
480480
typedef struct FinCapture {
481-
word32 cliFinSeq; /* client relative sequence FIN 0 is no */
482-
word32 srvFinSeq; /* server relative sequence FIN, 0 is no */
481+
word32 cliFinSeq; /* client relative sequence FIN (may be 0) */
482+
word32 srvFinSeq; /* server relative sequence FIN (may be 0) */
483+
byte cliHasFin; /* client FIN captured (seq value may be 0) */
484+
byte srvHasFin; /* server FIN captured (seq value may be 0) */
483485
byte cliCounted; /* did we count yet, detects duplicates */
484486
byte srvCounted; /* did we count yet, detects duplicates */
485487
} FinCapture;
@@ -5612,6 +5614,11 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
56125614
* data after the IP record for the FCS for Ethernet. */
56135615
*sslBytes = (int)(packet + ipInfo->total - *sslFrame);
56145616

5617+
if (*sslBytes < 0) {
5618+
SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
5619+
return WOLFSSL_FATAL_ERROR;
5620+
}
5621+
56155622
/* Ensure sslBytes does not exceed the actual size. */
56165623
if (*sslBytes > (int)(length - (ipInfo->length + tcpInfo->length))) {
56175624
SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
@@ -5821,12 +5828,16 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
58215828
static int AddFinCapture(SnifferSession* session, word32 sequence)
58225829
{
58235830
if (session->flags.side == WOLFSSL_SERVER_END) {
5824-
if (session->finCapture.cliCounted == 0)
5831+
if (session->finCapture.cliCounted == 0) {
58255832
session->finCapture.cliFinSeq = sequence;
5833+
session->finCapture.cliHasFin = 1;
5834+
}
58265835
}
58275836
else {
5828-
if (session->finCapture.srvCounted == 0)
5837+
if (session->finCapture.srvCounted == 0) {
58295838
session->finCapture.srvFinSeq = sequence;
5839+
session->finCapture.srvHasFin = 1;
5840+
}
58305841
}
58315842
return 1;
58325843
}
@@ -5837,6 +5848,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
58375848
int* sslBytes, const byte** sslFrame, char* error)
58385849
{
58395850
int ret = 0;
5851+
sword32 seqDiff;
58405852
word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
58415853
session->cliSeqStart : session->srvSeqStart;
58425854
word32* seqLast = (session->flags.side == WOLFSSL_SERVER_END) ?
@@ -5854,12 +5866,17 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
58545866
if (tcpInfo->sequence < seqStart)
58555867
real = 0xffffffffU - seqStart + tcpInfo->sequence + 1;
58565868

5869+
/* Relative sequence numbers wrap at 2^32, so order them with signed
5870+
* (RFC 1982) serial-number arithmetic; plain unsigned </> mis-handles
5871+
* the wrap boundary and would drop wrapped segments as already-seen. */
5872+
seqDiff = (sword32)(real - *expected);
5873+
58575874
TraceRelativeSequence(*expected, real);
58585875

5859-
if (real < *expected) {
5876+
if (seqDiff < 0) {
58605877
int overlap = *expected - real;
58615878

5862-
if (real + *sslBytes > *expected) {
5879+
if ((sword32)(real + (word32)*sslBytes - *expected) > 0) {
58635880
#ifdef WOLFSSL_ASYNC_CRYPT
58645881
if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) &&
58655882
session->pendSeq != tcpInfo->sequence)
@@ -5901,7 +5918,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
59015918
}
59025919
}
59035920
else if (*sslBytes > 0) {
5904-
if (real + *sslBytes - 1 > *seqLast) {
5921+
if ((sword32)(real + (word32)*sslBytes - 1 - *seqLast) > 0) {
59055922
/* fix segment overlap */
59065923
#ifdef DEBUG_SNIFFER
59075924
WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
@@ -5931,7 +5948,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
59315948
session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) &&
59325949
session->pendSeq != tcpInfo->sequence &&
59335950
#endif
5934-
real + *sslBytes -1 <= *seqLast) {
5951+
(sword32)(real + (word32)*sslBytes - 1 - *seqLast) <= 0) {
59355952
Trace(DUPLICATE_STR);
59365953
ret = 1;
59375954
}
@@ -5947,7 +5964,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
59475964
}
59485965
}
59495966
}
5950-
else if (real > *expected) {
5967+
else if (seqDiff > 0) {
59515968
Trace(OUT_OF_ORDER_STR);
59525969
if (*sslBytes > 0) {
59535970
int addResult = AddToReassembly(session->flags.side, real,
@@ -6141,7 +6158,13 @@ static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
61416158

61426159
TraceAck(real, expected);
61436160

6144-
if (real > expected)
6161+
/* Relative sequence numbers wrap at 2^32; compare with signed
6162+
* (RFC 1982) serial-number arithmetic to avoid a false positive at
6163+
* the wrap boundary. Expected is still 0 when that side's SYN was
6164+
* never seen, leaving no base to be relative to, so any data being
6165+
* ACKed there is data we missed. */
6166+
if ((expected == 0) ? (real != 0) :
6167+
((sword32)(real - expected) > 0))
61456168
return WOLFSSL_FATAL_ERROR; /* we missed a packet, ACKing data we never saw */
61466169
}
61476170
return 0;
@@ -6180,6 +6203,12 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
61806203

61816204
/* adjust potential ethernet trailer */
61826205
actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
6206+
/* CheckHeaders already rejects this for the current callers; kept so the
6207+
* clamp below cannot be reached with a negative bound. */
6208+
if (actualLen < 0) {
6209+
SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
6210+
return WOLFSSL_FATAL_ERROR;
6211+
}
61836212
if (*sslBytes > actualLen) {
61846213
*sslBytes = actualLen;
61856214
}
@@ -6725,17 +6754,23 @@ static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
67256754
SnifferSession* session)
67266755
{
67276756
int ret = 0;
6728-
if (session->finCapture.cliFinSeq && session->finCapture.cliFinSeq <=
6729-
session->cliExpected) {
6757+
/* FIN sequences are relative and wrap at 2^32, so compare "reached" with
6758+
* signed (RFC 1982) serial-number arithmetic. A dedicated has-FIN flag
6759+
* marks capture, since a relative sequence of 0 is itself a valid FIN
6760+
* position at the wrap boundary. */
6761+
if (session->finCapture.cliHasFin &&
6762+
(sword32)(session->finCapture.cliFinSeq - session->cliExpected)
6763+
<= 0) {
67306764
if (session->finCapture.cliCounted == 0) {
67316765
session->flags.finCount += 1;
67326766
session->finCapture.cliCounted = 1;
67336767
TraceClientFin(session->finCapture.cliFinSeq, session->cliExpected);
67346768
}
67356769
}
67366770

6737-
if (session->finCapture.srvFinSeq && session->finCapture.srvFinSeq <=
6738-
session->srvExpected) {
6771+
if (session->finCapture.srvHasFin &&
6772+
(sword32)(session->finCapture.srvFinSeq - session->srvExpected)
6773+
<= 0) {
67396774
if (session->finCapture.srvCounted == 0) {
67406775
session->flags.finCount += 1;
67416776
session->finCapture.srvCounted = 1;

src/ssl_crypto.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2672,6 +2672,12 @@ WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in,
26722672
* we are padding the last block. This is not a padding API.
26732673
* TODO: Validate parameters?
26742674
*
2675+
* A length that is not a multiple of DES_BLOCK_SIZE is rounded up to a whole
2676+
* block: on encrypt the trailing partial block is 0 padded and a full block is
2677+
* written to output, and on decrypt a full block is read from input. Both
2678+
* buffers must therefore hold length rounded up to DES_BLOCK_SIZE, not just
2679+
* length bytes.
2680+
*
26752681
* @param [in] input Data to encipher.
26762682
* @param [out] output Enciphered data.
26772683
* @param [in] length Length of data to encipher.
@@ -2740,6 +2746,10 @@ void wolfSSL_DES_cbc_encrypt(const unsigned char* input, unsigned char* output,
27402746
* we are padding the last block. This is not a padding API.
27412747
* TODO: Validate parameters?
27422748
*
2749+
* A length that is not a multiple of DES_BLOCK_SIZE is rounded up to a whole
2750+
* block, and the new IV is taken from that last whole block. Both buffers must
2751+
* therefore hold length rounded up to DES_BLOCK_SIZE, not just length bytes.
2752+
*
27432753
* @param [in] input Data to encipher.
27442754
* @param [out] output Enciphered data.
27452755
* @param [in] length Length of data to encipher.
@@ -2792,10 +2802,18 @@ void wolfSSL_DES_ncbc_encrypt(const unsigned char* input, unsigned char* output,
27922802
* we are padding the last block. This is not a padding API.
27932803
* TODO: Validate parameters?
27942804
*
2805+
* A size that is not a multiple of DES_BLOCK_SIZE is rounded up to a whole
2806+
* block: on encrypt the trailing partial block is 0 padded and a full block is
2807+
* written to output, and on decrypt a full block is read from input. Both
2808+
* buffers must therefore hold sz rounded up to DES_BLOCK_SIZE, not just sz
2809+
* bytes.
2810+
*
27952811
* @param [in] input Data to encipher.
27962812
* @param [out] output Enciphered data.
2797-
* @param [in] length Length of data to encipher.
2798-
* @param [in] schedule Key schedule.
2813+
* @param [in] sz Length of data to encipher.
2814+
* @param [in] ks1 First key schedule.
2815+
* @param [in] ks2 Second key schedule.
2816+
* @param [in] ks3 Third key schedule.
27992817
* @param [in, out] ivec IV for CBC operation.
28002818
* @param [in] enc Whether to encrypt.
28012819
*/

0 commit comments

Comments
 (0)