Fixing DTLS for 64-bit sequence numbering

1. Simplify away the DtlsState record.
2. Adding in high order bits for the DTLS sequence number.
3. For DTLS, separated copying the sequence number from incrementing it.
This commit is contained in:
John Safranek
2016-09-22 14:13:24 -07:00
parent 67a112773e
commit 4522fa335e
3 changed files with 271 additions and 209 deletions

View File

@ -121,8 +121,8 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#ifdef WOLFSSL_DTLS
static INLINE int DtlsCheckWindow(DtlsState* state);
static INLINE int DtlsUpdateWindow(DtlsState* state);
static INLINE int DtlsCheckWindow(WOLFSSL* ssl);
static INLINE int DtlsUpdateWindow(WOLFSSL* ssl);
#endif
@ -187,7 +187,7 @@ static INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
#ifdef WOLFSSL_DTLS
/* For DTLS, epoch 0 is always not encrypted. */
if (ssl->options.dtls && !isSend && ssl->keys.dtls_state.curEpoch == 0)
if (ssl->options.dtls && !isSend && ssl->keys.curEpoch == 0)
return 0;
#endif /* WOLFSSL_DTLS */
@ -336,21 +336,6 @@ void c32to24(word32 in, word24 out)
}
#ifdef WOLFSSL_DTLS
static INLINE void c32to48(word32 in, byte out[6])
{
out[0] = 0;
out[1] = 0;
out[2] = (in >> 24) & 0xff;
out[3] = (in >> 16) & 0xff;
out[4] = (in >> 8) & 0xff;
out[5] = in & 0xff;
}
#endif /* WOLFSSL_DTLS */
/* convert 16 bit integer to opaque */
static INLINE void c16toa(word16 u16, byte* c)
{
@ -586,11 +571,11 @@ 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->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->nextEpoch, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->nextSeq, exp + idx); idx += OPAQUE32_LEN;
c16toa(keys->curEpoch, exp + idx); idx += OPAQUE16_LEN;
c32toa(keys->curSeq, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->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);
@ -606,13 +591,13 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
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;
c64toa(keys->window, exp + idx); idx += OPAQUE64_LEN;
c64toa(keys->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;
c32toa(keys->window, exp + idx); idx += OPAQUE32_LEN;
c32toa(0, exp + idx); idx += OPAQUE32_LEN;
c32toa(keys->prevWindow, exp + idx); idx += OPAQUE32_LEN;
c32toa(0, exp + idx); idx += OPAQUE32_LEN;
#endif
#ifdef HAVE_TRUNCATED_HMAC
@ -712,11 +697,11 @@ 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->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->nextEpoch); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->nextSeq); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->curEpoch); idx += OPAQUE16_LEN;
ato32(exp + idx, &keys->curSeq); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->prevSeq); idx += OPAQUE32_LEN;
ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN;
ato16(exp + idx, &keys->dtls_expected_peer_handshake_number);
@ -732,13 +717,13 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
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;
ato64(exp + idx, &keys->window); idx += OPAQUE64_LEN;
ato64(exp + idx, &keys->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;
ato32(exp + idx, &keys->window); idx += OPAQUE32_LEN;
ato32(exp + idx, 0); idx += OPAQUE32_LEN;
ato32(exp + idx, &keys->prevWindow); idx += OPAQUE32_LEN;
ato32(exp + idx, 0); idx += OPAQUE32_LEN;
#endif
#ifdef HAVE_TRUNCATED_HMAC
@ -1046,7 +1031,7 @@ static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
return SOCKET_ERROR_E;
}
c16toa((word16)fam, exp + idx); idx += DTLS_EXPORT_LEN;
c16toa((word16)fam, exp + idx); idx += DTLS_EXPORT_LEN;
c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN;
XMEMCPY(exp + idx, ip, ipSz); idx += ipSz;
c16toa(port, exp + idx); idx += DTLS_EXPORT_LEN;
@ -3922,6 +3907,98 @@ void FreeSSL(WOLFSSL* ssl, void* heap)
}
#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
|| defined(HAVE_AESGCM)
static INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
{
if (verify) {
seq[0] = ssl->keys.peer_sequence_number_hi;
seq[1] = ssl->keys.peer_sequence_number_lo++;
if (seq[1] > ssl->keys.peer_sequence_number_lo) {
/* handle rollover */
ssl->keys.peer_sequence_number_hi++;
}
}
else {
seq[0] = ssl->keys.sequence_number_hi;
seq[1] = ssl->keys.sequence_number_lo++;
if (seq[1] > ssl->keys.sequence_number_lo) {
/* handle rollover */
ssl->keys.sequence_number_hi++;
}
}
}
#ifdef WOLFSSL_DTLS
static INLINE void DtlsGetSEQ(WOLFSSL* ssl, int verify, word32 seq[2])
{
if (verify == -1) {
/* Previous epoch case */
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 (verify == 1) {
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);
seq[1] = ssl->keys.dtls_sequence_number_lo;
}
}
static INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int verify)
{
word32 seq;
if (verify == -1) {
seq = ssl->keys.dtls_prev_sequence_number_lo++;
if (seq > ssl->keys.dtls_prev_sequence_number_lo) {
/* handle rollover */
ssl->keys.dtls_prev_sequence_number_hi++;
}
}
else if (verify == 1) {
seq = ssl->keys.peer_sequence_number_lo++;
if (seq > ssl->keys.peer_sequence_number_lo) {
/* handle rollover */
ssl->keys.peer_sequence_number_hi++;
}
}
else {
seq = ssl->keys.dtls_sequence_number_lo++;
if (seq > ssl->keys.dtls_sequence_number_lo) {
/* handle rollover */
ssl->keys.dtls_sequence_number_hi++;
}
}
}
#endif /* WOLFSSL_DTLS */
static INLINE void WriteSEQ(WOLFSSL* ssl, int verify, byte* out)
{
word32 seq[2];
if (!ssl->options.dtls) {
GetSEQIncrement(ssl, verify, seq);
}
else {
#ifdef WOLFSSL_DTLS
DtlsGetSEQ(ssl, verify, seq);
#endif
}
c32toa(seq[0], out);
c32toa(seq[1], out+4);
}
#endif
#ifdef WOLFSSL_DTLS
int DtlsPoolInit(WOLFSSL* ssl)
@ -4022,13 +4099,13 @@ int DtlsPoolSend(WOLFSSL* ssl)
for (i = 0, buf = pool->buf; i < pool->used; i++, buf++) {
if (pool->epoch[i] == 0) {
DtlsRecordLayerHeader* dtls;
word32* seqNumber;
int epochZero;
dtls = (DtlsRecordLayerHeader*)buf->buffer;
seqNumber = (ssl->keys.dtls_epoch == 0) ?
&ssl->keys.dtls_sequence_number :
&ssl->keys.dtls_prev_sequence_number;
c32to48((*seqNumber)++, dtls->sequence_number);
epochZero = (ssl->keys.dtls_epoch == 0) ? 0 : -1;
WriteSEQ(ssl, epochZero, dtls->sequence_number);
DtlsSEQIncrement(ssl, epochZero);
if ((ret = CheckAvailableSize(ssl, buf->length)) != 0)
return ret;
@ -4694,8 +4771,7 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl
/* dtls record layer header extensions */
dtls = (DtlsRecordLayerHeader*)output;
c16toa(ssl->keys.dtls_epoch, dtls->epoch);
c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number);
WriteSEQ(ssl, 0, dtls->sequence_number);
c16toa((word16)length, dtls->length);
#endif
}
@ -5085,9 +5161,11 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* type and version in same sport */
XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
*inOutIdx += ENUM_LEN + VERSION_SZ;
ato16(input + *inOutIdx, &ssl->keys.dtls_state.curEpoch);
*inOutIdx += 4; /* advance past epoch, skip first 2 seq bytes for now */
ato32(input + *inOutIdx, &ssl->keys.dtls_state.curSeq);
ato16(input + *inOutIdx, &ssl->keys.curEpoch);
*inOutIdx += 2;
ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
*inOutIdx += 2;
ato32(input + *inOutIdx, &ssl->keys.curSeq_lo);
*inOutIdx += 4; /* advance past rest of seq */
ato16(input + *inOutIdx, size);
*inOutIdx += LENGTH_SZ;
@ -5096,8 +5174,8 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl) &&
(!DtlsCheckWindow(&ssl->keys.dtls_state) ||
(ssl->options.handShakeDone && ssl->keys.dtls_state.curEpoch == 0))) {
(!DtlsCheckWindow(ssl) ||
(ssl->options.handShakeDone && ssl->keys.curEpoch == 0))) {
return SEQUENCE_ERROR;
}
#endif
@ -7680,33 +7758,35 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#ifdef WOLFSSL_DTLS
static INLINE int DtlsCheckWindow(DtlsState* state)
static INLINE int DtlsCheckWindow(WOLFSSL* ssl)
{
word32 cur;
word32 next;
word32 cur_hi, cur_lo, next_hi, next_lo;
DtlsSeq window;
if (state->curEpoch == state->nextEpoch) {
next = state->nextSeq;
window = state->window;
if (ssl->keys.curEpoch == ssl->keys.nextEpoch) {
next_hi = ssl->keys.nextSeq_hi;
next_lo = ssl->keys.nextSeq_lo;
window = ssl->keys.window;
}
else if (state->curEpoch == state->nextEpoch - 1) {
next = state->prevSeq;
window = state->prevWindow;
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;
}
else {
return 0;
}
/* XXX Handle rollover */
cur_hi = ssl->keys.curSeq_hi;
cur_lo = ssl->keys.curSeq_lo;
cur = state->curSeq;
if ((next > DTLS_SEQ_BITS) && (cur < next - DTLS_SEQ_BITS)) {
if ((next_lo > DTLS_SEQ_BITS) && (cur_lo < next_lo - DTLS_SEQ_BITS)) {
return 0;
}
else if ((cur < next) && (window & ((DtlsSeq)1 << (next - cur - 1)))) {
else if ((cur_lo < next_lo) && (window & ((DtlsSeq)1 << (next_lo - cur_lo - 1)))) {
return 0;
}
else if (cur > next + DTLS_SEQ_BITS) {
else if (cur_lo > next_lo + DTLS_SEQ_BITS) {
return 0;
}
@ -7714,22 +7794,22 @@ static INLINE int DtlsCheckWindow(DtlsState* state)
}
static INLINE int DtlsUpdateWindow(DtlsState* state)
static INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
{
word32 cur;
word32* next;
DtlsSeq* window;
if (state->curEpoch == state->nextEpoch) {
next = &state->nextSeq;
window = &state->window;
if (ssl->keys.curEpoch == ssl->keys.nextEpoch) {
next = &ssl->keys.nextSeq_lo;
window = &ssl->keys.window;
}
else {
next = &state->prevSeq;
window = &state->prevWindow;
next = &ssl->keys.prevSeq_lo;
window = &ssl->keys.prevWindow;
}
cur = state->curSeq;
cur = ssl->keys.curSeq_lo;
if (cur < *next) {
*window |= ((DtlsSeq)1 << (*next - cur - 1));
@ -7864,55 +7944,6 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif
#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
|| defined(HAVE_AESGCM)
static INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
{
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if (verify) {
seq[0] = 0;
seq[1] = ssl->keys.dtls_state.curSeq; /* explicit from peer */
}
else {
seq[0] = 0;
/* already incremented dtls seq number */
seq[1] = ssl->keys.dtls_sequence_number - 1;
}
return;
}
#endif
if (verify) {
seq[0] = ssl->keys.peer_sequence_number_hi;
seq[1] = ssl->keys.peer_sequence_number_lo++;
if (seq[1] > ssl->keys.peer_sequence_number_lo) {
/* handle rollover */
ssl->keys.peer_sequence_number_hi++;
}
}
else {
seq[0] = ssl->keys.sequence_number_hi;
seq[1] = ssl->keys.sequence_number_lo++;
if (seq[1] > ssl->keys.sequence_number_lo) {
/* handle rollover */
ssl->keys.sequence_number_hi++;
}
}
}
static INLINE void WriteSEQ(WOLFSSL* ssl, int verify, byte* out)
{
word32 seq[2];
GetSEQIncrement(ssl, verify, seq);
c32toa(seq[0], out);
c32toa(seq[1], out+4);
}
#endif
#ifdef HAVE_AEAD
static INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
{
@ -7998,7 +8029,7 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
if (ssl->options.oldPoly != 0) {
/* get nonce */
c32toa(ssl->keys.sequence_number_lo, nonce + CHACHA20_OLD_OFFSET);
WriteSEQ(ssl, 0, nonce + CHACHA20_OLD_OFFSET);
}
/* opaque SEQ number stored for AD */
@ -8008,8 +8039,8 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
* the input buffer ahead of the plaintext. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
c16toa(ssl->keys.dtls_epoch, add);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
DtlsSEQIncrement(ssl, 0);
}
#endif
@ -8142,23 +8173,18 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
if (ssl->options.oldPoly != 0) {
/* get nonce */
c32toa(ssl->keys.peer_sequence_number_lo, nonce + CHACHA20_OLD_OFFSET);
WriteSEQ(ssl, 1, nonce + CHACHA20_OLD_OFFSET);
}
/* sequence number field is 64-bits */
WriteSEQ(ssl, 1, add);
/* get AD info */
/* Store the type, version. */
add[AEAD_TYPE_OFFSET] = ssl->curRL.type;
add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
/* Store the type, version. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
c16toa(ssl->keys.dtls_state.curEpoch, add);
#endif
/* add TLS message size to additional data */
add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff;
@ -8300,7 +8326,6 @@ static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz)
* the input buffer ahead of the plaintext. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
c16toa(ssl->keys.dtls_epoch, additional);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
}
#endif
@ -8323,6 +8348,10 @@ static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz)
additional, AEAD_AUTH_DATA_SZ);
AeadIncrementExpIV(ssl);
ForceZero(nonce, AESGCM_NONCE_SZ);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
}
break;
#endif
@ -8344,7 +8373,6 @@ static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz)
* the input buffer ahead of the plaintext. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
c16toa(ssl->keys.dtls_epoch, additional);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
}
#endif
@ -8367,6 +8395,10 @@ static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz)
additional, AEAD_AUTH_DATA_SZ);
AeadIncrementExpIV(ssl);
ForceZero(nonce, AESGCM_NONCE_SZ);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
}
break;
#endif
@ -8463,11 +8495,6 @@ static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
/* sequence number field is 64-bits */
WriteSEQ(ssl, 1, additional);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
c16toa(ssl->keys.dtls_state.curEpoch, additional);
#endif
additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
@ -8505,11 +8532,6 @@ static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
/* sequence number field is 64-bits */
WriteSEQ(ssl, 1, additional);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
c16toa(ssl->keys.dtls_state.curEpoch, additional);
#endif
additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
@ -9353,7 +9375,7 @@ int ProcessReply(WOLFSSL* ssl)
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl)) {
DtlsUpdateWindow(&ssl->keys.dtls_state);
DtlsUpdateWindow(ssl);
}
#endif /* WOLFSSL_DTLS */
@ -9463,8 +9485,8 @@ int ProcessReply(WOLFSSL* ssl)
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
DtlsPoolReset(ssl);
ssl->keys.dtls_state.nextEpoch++;
ssl->keys.dtls_state.nextSeq = 0;
ssl->keys.nextEpoch++;
ssl->keys.nextSeq_lo = 0;
}
#endif
@ -9975,6 +9997,10 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
#endif
ret = ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz,
type, 0);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
}
if (ret != 0)
return ret;
@ -10012,9 +10038,12 @@ int SendFinished(WOLFSSL* ssl)
if (ssl->options.dtls) {
headerSz += DTLS_HANDSHAKE_EXTRA;
ssl->keys.dtls_epoch++;
ssl->keys.dtls_prev_sequence_number =
ssl->keys.dtls_sequence_number;
ssl->keys.dtls_sequence_number = 0;
ssl->keys.dtls_prev_sequence_number_hi =
ssl->keys.dtls_sequence_number_hi;
ssl->keys.dtls_prev_sequence_number_lo =
ssl->keys.dtls_sequence_number_lo;
ssl->keys.dtls_sequence_number_hi = 0;
ssl->keys.dtls_sequence_number_lo = 0;
}
#endif
@ -10199,7 +10228,6 @@ int SendCertificate(WOLFSSL* ssl)
HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA);
/* Adding the headers increments these, decrement them for
* actual message header. */
ssl->keys.dtls_sequence_number--;
ssl->keys.dtls_handshake_number--;
AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
ssl->keys.dtls_handshake_number--;
@ -10286,6 +10314,10 @@ int SendCertificate(WOLFSSL* ssl)
if (sendSz < 0)
return sendSz;
}
else {
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
}
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl)) {
@ -10310,10 +10342,7 @@ int SendCertificate(WOLFSSL* ssl)
if (ret != WANT_WRITE) {
/* Clean up the fragment offset. */
ssl->fragOffset = 0;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
ssl->keys.dtls_handshake_number++;
#endif
ssl->keys.dtls_handshake_number++;
if (ssl->options.side == WOLFSSL_SERVER_END)
ssl->options.serverState = SERVER_CERT_COMPLETE;
}
@ -10387,6 +10416,8 @@ int SendCertificateRequest(WOLFSSL* ssl)
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
}
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
ret = HashOutput(ssl, output, sendSz, 0);
@ -10478,8 +10509,13 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
if (sendSz < 0)
ret = sendSz;
}
else
else {
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
ret = HashOutput(ssl, output, sendSz, 0);
}
#ifdef WOLFSSL_DTLS
if (ret == 0 && IsDtlsNotSctpMode(ssl))
@ -12911,6 +12947,10 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
if (sendSz < 0)
return sendSz;
} else {
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0)
return ret;
@ -15431,6 +15471,10 @@ int SendClientKeyExchange(WOLFSSL* ssl)
}
}
else {
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0) {
goto exit_scke;
@ -15911,6 +15955,10 @@ int SendCertificateVerify(WOLFSSL* ssl)
}
}
else {
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
ret = HashOutput(ssl, output, sendSz, 0);
}
@ -16134,7 +16182,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->options.dtls) {
/* Server Hello should use the same sequence number as the
* Client Hello. */
ssl->keys.dtls_sequence_number = ssl->keys.dtls_state.curSeq;
ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
}
@ -16214,6 +16263,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
}
if (ssl->options.dtls) {
DtlsSEQIncrement(ssl, 0);
}
#endif
ret = HashOutput(ssl, output, sendSz, 0);
@ -17539,6 +17592,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_sske;
}
}
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
ret = HashOutput(ssl, output, sendSz, 0);
@ -18757,6 +18813,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return 0;
}
if (ssl->options.dtls)
DtlsSEQIncrement(ssl, 0);
#endif
ret = HashOutput(ssl, output, sendSz, 0);
@ -18975,6 +19034,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
DtlsSEQIncrement(ssl, 0);
}
#endif
@ -19008,7 +19069,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* Hello Verify Request should use the same sequence number as the
* Client Hello. */
ssl->keys.dtls_sequence_number = ssl->keys.dtls_state.curSeq;
ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
AddHeaders(output, length, hello_verify_request, ssl);
#ifdef OPENSSL_EXTRA

View File

@ -644,20 +644,6 @@ static INLINE void c32toa(word32 u32, byte* c)
static INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
{
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if (verify) {
seq[0] = 0;
seq[1] = ssl->keys.dtls_state.curSeq; /* explicit from peer */
}
else {
seq[0] = 0;
/* already incremented dtls seq number */
seq[1] = ssl->keys.dtls_sequence_number - 1;
}
return;
}
#endif
if (verify) {
seq[0] = ssl->keys.peer_sequence_number_hi;
seq[1] = ssl->keys.peer_sequence_number_lo++;
@ -677,30 +663,47 @@ static INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
}
#ifdef WOLFSSL_DTLS
static INLINE void DtlsGetSEQ(WOLFSSL* ssl, int verify, word32 seq[2])
{
if (verify == -1) {
/* Previous epoch case */
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 (verify == 1) {
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);
seq[1] = ssl->keys.dtls_sequence_number_lo;
}
}
#endif /* WOLFSSL_DTLS */
static INLINE void WriteSEQ(WOLFSSL* ssl, int verify, byte* out)
{
word32 seq[2];
GetSEQIncrement(ssl, verify, seq);
if (!ssl->options.dtls) {
GetSEQIncrement(ssl, verify, seq);
}
else {
#ifdef WOLFSSL_DTLS
DtlsGetSEQ(ssl, verify, seq);
#endif
}
c32toa(seq[0], out);
c32toa(seq[1], out+4);
}
#ifdef WOLFSSL_DTLS
static INLINE word32 GetEpoch(WOLFSSL* ssl, int verify)
{
if (verify)
return ssl->keys.dtls_state.curEpoch;
else
return ssl->keys.dtls_epoch;
}
#endif /* WOLFSSL_DTLS */
/*** end copy ***/
@ -758,10 +761,6 @@ int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content,
XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
c16toa((word16)GetEpoch(ssl, verify), inner);
#endif
WriteSEQ(ssl, verify, inner);
inner[SEQ_SZ] = (byte)content;
inner[SEQ_SZ + ENUM_LEN] = ssl->version.major;

View File

@ -994,7 +994,7 @@ enum Misc {
CHACHA20_IMP_IV_SZ = 12, /* Size of ChaCha20 AEAD implicit IV */
CHACHA20_NONCE_SZ = 12, /* Size of ChacCha20 nonce */
CHACHA20_OLD_OFFSET = 8, /* Offset for seq # in old poly1305 */
CHACHA20_OLD_OFFSET = 4, /* Offset for seq # in old poly1305 */
/* For any new implicit/explicit IV size adjust AEAD_MAX_***_SZ */
@ -1581,18 +1581,6 @@ typedef struct WOLFSSL_DTLS_CTX {
#endif
#define DTLS_SEQ_BITS (sizeof(DtlsSeq) * CHAR_BIT)
typedef struct DtlsState {
DtlsSeq window; /* Sliding window for current epoch */
word16 nextEpoch; /* Expected epoch in next record */
word32 nextSeq; /* Expected sequence in next record */
word16 curEpoch; /* Received epoch in current record */
word32 curSeq; /* Received sequence in current record */
DtlsSeq prevWindow; /* Sliding window for old epoch */
word32 prevSeq; /* Next sequence in allowed old epoch */
} DtlsState;
#endif /* WOLFSSL_DTLS */
@ -1619,13 +1607,27 @@ typedef struct Keys {
word32 sequence_number_lo;
#ifdef WOLFSSL_DTLS
DtlsState dtls_state; /* Peer's state */
DtlsSeq window; /* 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;
DtlsSeq prevWindow; /* Sliding window for old epoch */
word16 prevSeq_hi; /* Next sequence in allowed old epoch */
word32 prevSeq_lo;
word16 dtls_peer_handshake_number;
word16 dtls_expected_peer_handshake_number;
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_epoch; /* Current epoch */
word32 dtls_sequence_number_hi; /* Current epoch */
word32 dtls_sequence_number_lo;
word32 dtls_prev_sequence_number_hi; /* Previous epoch */
word32 dtls_prev_sequence_number_lo;
word16 dtls_handshake_number; /* Current tx handshake seq */
#endif
@ -2569,8 +2571,7 @@ typedef struct DtlsRecordLayerHeader {
byte type;
byte pvMajor;
byte pvMinor;
byte epoch[2]; /* increment on cipher state change */
byte sequence_number[6]; /* per record */
byte sequence_number[8]; /* per record */
byte length[2];
} DtlsRecordLayerHeader;