mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 04:04:39 +02:00
improved DTLS handshake sequence numbering when retransmitting finished message
This commit is contained in:
151
src/internal.c
151
src/internal.c
@@ -84,7 +84,7 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
|
static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
|
||||||
const byte* input, int inSz, int type);
|
const byte* input, int inSz, int type, int hashOutput);
|
||||||
|
|
||||||
#ifndef NO_WOLFSSL_CLIENT
|
#ifndef NO_WOLFSSL_CLIENT
|
||||||
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*,
|
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*,
|
||||||
@@ -2282,6 +2282,7 @@ int DtlsPoolSave(WOLFSSL* ssl, const byte *src, int sz)
|
|||||||
return MEMORY_ERROR;
|
return MEMORY_ERROR;
|
||||||
}
|
}
|
||||||
XMEMCPY(pBuf->buffer, src, sz);
|
XMEMCPY(pBuf->buffer, src, sz);
|
||||||
|
pool->epoch[pool->used] = ssl->keys.dtls_epoch;
|
||||||
pBuf->length = (word32)sz;
|
pBuf->length = (word32)sz;
|
||||||
pool->used++;
|
pool->used++;
|
||||||
}
|
}
|
||||||
@@ -2331,40 +2332,53 @@ int DtlsPoolTimeout(WOLFSSL* ssl)
|
|||||||
|
|
||||||
int DtlsPoolSend(WOLFSSL* ssl)
|
int DtlsPoolSend(WOLFSSL* ssl)
|
||||||
{
|
{
|
||||||
int ret;
|
DtlsPool* pool = ssl->dtls_pool;
|
||||||
DtlsPool *pool = ssl->dtls_pool;
|
|
||||||
|
|
||||||
if (pool != NULL && pool->used > 0) {
|
if (pool != NULL && pool->used > 0) {
|
||||||
int i;
|
int ret = 0;
|
||||||
for (i = 0; i < pool->used; i++) {
|
int i;
|
||||||
int sendResult;
|
buffer* buf;
|
||||||
buffer* buf = &pool->buf[i];
|
|
||||||
|
|
||||||
DtlsRecordLayerHeader* dtls = (DtlsRecordLayerHeader*)buf->buffer;
|
for (i = 0, buf = pool->buf; i < pool->used; i++, buf++) {
|
||||||
|
if (pool->epoch[i] == 0) {
|
||||||
|
DtlsRecordLayerHeader* dtls;
|
||||||
|
|
||||||
word16 message_epoch;
|
dtls = (DtlsRecordLayerHeader*)buf->buffer;
|
||||||
ato16(dtls->epoch, &message_epoch);
|
c32to48(ssl->keys.dtls_prev_sequence_number++,
|
||||||
if (message_epoch == ssl->keys.dtls_epoch) {
|
dtls->sequence_number);
|
||||||
/* Increment record sequence number on retransmitted handshake
|
if ((ret = CheckAvailableSize(ssl, buf->length)) != 0)
|
||||||
* messages */
|
return ret;
|
||||||
c32to48(ssl->keys.dtls_sequence_number, dtls->sequence_number);
|
|
||||||
ssl->keys.dtls_sequence_number++;
|
XMEMCPY(ssl->buffers.outputBuffer.buffer,
|
||||||
|
buf->buffer, buf->length);
|
||||||
|
ssl->buffers.outputBuffer.idx = 0;
|
||||||
|
ssl->buffers.outputBuffer.length = buf->length;
|
||||||
}
|
}
|
||||||
else {
|
else if (pool->epoch[i] == ssl->keys.dtls_epoch) {
|
||||||
/* The Finished message is sent with the next epoch, keep its
|
byte* input;
|
||||||
* sequence number */
|
byte* output;
|
||||||
|
int inputSz, sendSz;
|
||||||
|
|
||||||
|
input = buf->buffer;
|
||||||
|
inputSz = buf->length;
|
||||||
|
sendSz = inputSz + MAX_MSG_EXTRA;
|
||||||
|
|
||||||
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
output = ssl->buffers.outputBuffer.buffer +
|
||||||
|
ssl->buffers.outputBuffer.length;
|
||||||
|
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
|
||||||
|
handshake, 0);
|
||||||
|
if (sendSz < 0)
|
||||||
|
return BUILD_MSG_ERROR;
|
||||||
|
|
||||||
|
ssl->buffers.outputBuffer.length += sendSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = CheckAvailableSize(ssl, buf->length)) != 0)
|
ret = SendBuffered(ssl);
|
||||||
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
XMEMCPY(ssl->buffers.outputBuffer.buffer, buf->buffer, buf->length);
|
|
||||||
ssl->buffers.outputBuffer.idx = 0;
|
|
||||||
ssl->buffers.outputBuffer.length = buf->length;
|
|
||||||
|
|
||||||
sendResult = SendBuffered(ssl);
|
|
||||||
if (sendResult < 0) {
|
|
||||||
return sendResult;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5091,14 +5105,6 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
|
|||||||
if (!ssl->options.resuming) {
|
if (!ssl->options.resuming) {
|
||||||
ssl->options.handShakeState = HANDSHAKE_DONE;
|
ssl->options.handShakeState = HANDSHAKE_DONE;
|
||||||
ssl->options.handShakeDone = 1;
|
ssl->options.handShakeDone = 1;
|
||||||
|
|
||||||
#ifdef WOLFSSL_DTLS
|
|
||||||
if (ssl->options.dtls) {
|
|
||||||
/* Other side has received our Finished, go to next epoch */
|
|
||||||
ssl->keys.dtls_epoch++;
|
|
||||||
ssl->keys.dtls_sequence_number = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -5106,14 +5112,6 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
|
|||||||
if (ssl->options.resuming) {
|
if (ssl->options.resuming) {
|
||||||
ssl->options.handShakeState = HANDSHAKE_DONE;
|
ssl->options.handShakeState = HANDSHAKE_DONE;
|
||||||
ssl->options.handShakeDone = 1;
|
ssl->options.handShakeDone = 1;
|
||||||
|
|
||||||
#ifdef WOLFSSL_DTLS
|
|
||||||
if (ssl->options.dtls) {
|
|
||||||
/* Other side has received our Finished, go to next epoch */
|
|
||||||
ssl->keys.dtls_epoch++;
|
|
||||||
ssl->keys.dtls_sequence_number = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7464,7 +7462,7 @@ int SendChangeCipher(WOLFSSL* ssl)
|
|||||||
|
|
||||||
input[0] = 1; /* turn it on */
|
input[0] = 1; /* turn it on */
|
||||||
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
|
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
|
||||||
change_cipher_spec);
|
change_cipher_spec, 0);
|
||||||
if (sendSz < 0)
|
if (sendSz < 0)
|
||||||
return sendSz;
|
return sendSz;
|
||||||
}
|
}
|
||||||
@@ -7694,7 +7692,7 @@ static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes)
|
|||||||
|
|
||||||
/* Build SSL Message, encrypted */
|
/* Build SSL Message, encrypted */
|
||||||
static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
|
static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
|
||||||
const byte* input, int inSz, int type)
|
const byte* input, int inSz, int type, int hashOutput)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_TRUNCATED_HMAC
|
#ifdef HAVE_TRUNCATED_HMAC
|
||||||
word32 digestSz = min(ssl->specs.hash_size,
|
word32 digestSz = min(ssl->specs.hash_size,
|
||||||
@@ -7769,7 +7767,7 @@ static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
|
|||||||
XMEMCPY(output + idx, input, inSz);
|
XMEMCPY(output + idx, input, inSz);
|
||||||
idx += inSz;
|
idx += inSz;
|
||||||
|
|
||||||
if (type == handshake) {
|
if (type == handshake && hashOutput) {
|
||||||
ret = HashOutput(ssl, output, headerSz + inSz, ivSz);
|
ret = HashOutput(ssl, output, headerSz + inSz, ivSz);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -7843,11 +7841,6 @@ int SendFinished(WOLFSSL* ssl)
|
|||||||
int headerSz = HANDSHAKE_HEADER_SZ;
|
int headerSz = HANDSHAKE_HEADER_SZ;
|
||||||
int outputSz;
|
int outputSz;
|
||||||
|
|
||||||
#ifdef WOLFSSL_DTLS
|
|
||||||
word32 sequence_number = ssl->keys.dtls_sequence_number;
|
|
||||||
word16 epoch = ssl->keys.dtls_epoch;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* setup encrypt keys */
|
/* setup encrypt keys */
|
||||||
if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
|
if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -7859,11 +7852,11 @@ int SendFinished(WOLFSSL* ssl)
|
|||||||
|
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
if (ssl->options.dtls) {
|
if (ssl->options.dtls) {
|
||||||
/* Send Finished message with the next epoch, but don't commit that
|
|
||||||
* change until the other end confirms its reception. */
|
|
||||||
headerSz += DTLS_HANDSHAKE_EXTRA;
|
headerSz += DTLS_HANDSHAKE_EXTRA;
|
||||||
ssl->keys.dtls_epoch++;
|
ssl->keys.dtls_epoch++;
|
||||||
ssl->keys.dtls_sequence_number = 0; /* reset after epoch change */
|
ssl->keys.dtls_prev_sequence_number =
|
||||||
|
ssl->keys.dtls_sequence_number;
|
||||||
|
ssl->keys.dtls_sequence_number = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -7890,18 +7883,18 @@ int SendFinished(WOLFSSL* ssl)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
if (ssl->options.dtls) {
|
||||||
|
if ((ret = DtlsPoolSave(ssl, input, headerSz + finishedSz)) != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz,
|
sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz,
|
||||||
handshake);
|
handshake, 1);
|
||||||
if (sendSz < 0)
|
if (sendSz < 0)
|
||||||
return BUILD_MSG_ERROR;
|
return BUILD_MSG_ERROR;
|
||||||
|
|
||||||
#ifdef WOLFSSL_DTLS
|
|
||||||
if (ssl->options.dtls) {
|
|
||||||
ssl->keys.dtls_epoch = epoch;
|
|
||||||
ssl->keys.dtls_sequence_number = sequence_number;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!ssl->options.resuming) {
|
if (!ssl->options.resuming) {
|
||||||
#ifndef NO_SESSION_CACHE
|
#ifndef NO_SESSION_CACHE
|
||||||
AddSession(ssl); /* just try */
|
AddSession(ssl); /* just try */
|
||||||
@@ -7909,36 +7902,14 @@ int SendFinished(WOLFSSL* ssl)
|
|||||||
if (ssl->options.side == WOLFSSL_SERVER_END) {
|
if (ssl->options.side == WOLFSSL_SERVER_END) {
|
||||||
ssl->options.handShakeState = HANDSHAKE_DONE;
|
ssl->options.handShakeState = HANDSHAKE_DONE;
|
||||||
ssl->options.handShakeDone = 1;
|
ssl->options.handShakeDone = 1;
|
||||||
#ifdef WOLFSSL_DTLS
|
|
||||||
if (ssl->options.dtls) {
|
|
||||||
/* Other side will soon receive our Finished, go to next
|
|
||||||
* epoch. */
|
|
||||||
ssl->keys.dtls_epoch++;
|
|
||||||
ssl->keys.dtls_sequence_number = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ssl->options.side == WOLFSSL_CLIENT_END) {
|
if (ssl->options.side == WOLFSSL_CLIENT_END) {
|
||||||
ssl->options.handShakeState = HANDSHAKE_DONE;
|
ssl->options.handShakeState = HANDSHAKE_DONE;
|
||||||
ssl->options.handShakeDone = 1;
|
ssl->options.handShakeDone = 1;
|
||||||
#ifdef WOLFSSL_DTLS
|
|
||||||
if (ssl->options.dtls) {
|
|
||||||
/* Other side will soon receive our Finished, go to next
|
|
||||||
* epoch. */
|
|
||||||
ssl->keys.dtls_epoch++;
|
|
||||||
ssl->keys.dtls_sequence_number = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef WOLFSSL_DTLS
|
|
||||||
if (ssl->options.dtls) {
|
|
||||||
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_CALLBACKS
|
#ifdef WOLFSSL_CALLBACKS
|
||||||
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
|
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
|
||||||
@@ -8146,7 +8117,7 @@ int SendCertificate(WOLFSSL* ssl)
|
|||||||
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
|
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendSz = BuildMessage(ssl, output, sendSz, input,inputSz,handshake);
|
sendSz = BuildMessage(ssl, output,sendSz,input,inputSz,handshake,1);
|
||||||
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
if (sendSz < 0)
|
if (sendSz < 0)
|
||||||
@@ -8361,7 +8332,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz,
|
sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz,
|
||||||
application_data);
|
application_data, 0);
|
||||||
if (sendSz < 0)
|
if (sendSz < 0)
|
||||||
return BUILD_MSG_ERROR;
|
return BUILD_MSG_ERROR;
|
||||||
|
|
||||||
@@ -8512,7 +8483,7 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
|
|||||||
/* only send encrypted alert if handshake actually complete, otherwise
|
/* only send encrypted alert if handshake actually complete, otherwise
|
||||||
other side may not be able to handle it */
|
other side may not be able to handle it */
|
||||||
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
|
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
|
||||||
sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert);
|
sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE,alert,0);
|
||||||
else {
|
else {
|
||||||
|
|
||||||
AddRecordHeader(output, ALERT_SIZE, alert, ssl);
|
AddRecordHeader(output, ALERT_SIZE, alert, ssl);
|
||||||
@@ -10141,7 +10112,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
|
|||||||
return MEMORY_E;
|
return MEMORY_E;
|
||||||
|
|
||||||
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
|
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
|
||||||
sendSz = BuildMessage(ssl, output, sendSz, input,inputSz,handshake);
|
sendSz = BuildMessage(ssl, output,sendSz,input,inputSz,handshake,1);
|
||||||
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
if (sendSz < 0)
|
if (sendSz < 0)
|
||||||
@@ -12313,7 +12284,7 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer)
|
|||||||
|
|
||||||
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
|
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
|
||||||
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
|
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
|
||||||
handshake);
|
handshake, 1);
|
||||||
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
if (sendSz < 0) {
|
if (sendSz < 0) {
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
@@ -12686,7 +12657,7 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer)
|
|||||||
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
|
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
|
||||||
sendSz = BuildMessage(ssl, output,
|
sendSz = BuildMessage(ssl, output,
|
||||||
MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA,
|
MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA,
|
||||||
input, inputSz, handshake);
|
input, inputSz, handshake, 1);
|
||||||
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
if (sendSz < 0)
|
if (sendSz < 0)
|
||||||
|
@@ -1445,8 +1445,9 @@ typedef struct Keys {
|
|||||||
word16 dtls_peer_handshake_number;
|
word16 dtls_peer_handshake_number;
|
||||||
word16 dtls_expected_peer_handshake_number;
|
word16 dtls_expected_peer_handshake_number;
|
||||||
|
|
||||||
word16 dtls_epoch; /* Current tx epoch */
|
|
||||||
word32 dtls_sequence_number; /* Current tx sequence */
|
word32 dtls_sequence_number; /* Current tx sequence */
|
||||||
|
word32 dtls_prev_sequence_number; /* Previous epoch's seq number*/
|
||||||
|
word16 dtls_epoch; /* Current tx epoch */
|
||||||
word16 dtls_handshake_number; /* Current tx handshake seq */
|
word16 dtls_handshake_number; /* Current tx handshake seq */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2289,6 +2290,7 @@ typedef struct DtlsRecordLayerHeader {
|
|||||||
|
|
||||||
typedef struct DtlsPool {
|
typedef struct DtlsPool {
|
||||||
buffer buf[DTLS_POOL_SZ];
|
buffer buf[DTLS_POOL_SZ];
|
||||||
|
word16 epoch[DTLS_POOL_SZ];
|
||||||
int used;
|
int used;
|
||||||
} DtlsPool;
|
} DtlsPool;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user