Skip to content

Commit 74ac2cd

Browse files
committed
dtls 1.3: pad plaintext when too short for record header protection
1 parent 29f51b6 commit 74ac2cd

3 files changed

Lines changed: 44 additions & 13 deletions

File tree

src/dtls13.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,11 @@ int Dtls13HandshakeAddHeader(WOLFSSL* ssl, byte* output,
12091209
return 0;
12101210
}
12111211

1212+
int Dtls13MinimumRecordLength(WOLFSSL* ssl)
1213+
{
1214+
return Dtls13GetRlHeaderLength(ssl, 1) + DTLS13_MIN_CIPHERTEXT;
1215+
}
1216+
12121217
/**
12131218
* Dtls13EncryptRecordNumber() - encrypt record number in the header
12141219
* @ssl: ssl object
@@ -1225,9 +1230,15 @@ int Dtls13EncryptRecordNumber(WOLFSSL* ssl, byte* hdr, word16 recordLength)
12251230
if (ssl == NULL || hdr == NULL)
12261231
return BAD_FUNC_ARG;
12271232

1233+
#ifdef HAVE_NULL_CIPHER
1234+
/* Do not encrypt record numbers with null cipher. See RFC 9150 Sec 9 */
1235+
if (ssl->specs.bulk_cipher_algorithm == wolfssl_cipher_null)
1236+
return 0;
1237+
#endif /*HAVE_NULL_CIPHER */
1238+
12281239
/* we need at least a 16 bytes of ciphertext to encrypt record number see
12291240
4.2.3*/
1230-
if (recordLength < Dtls13GetRlHeaderLength(ssl, 1) + DTLS13_MIN_CIPHERTEXT)
1241+
if (recordLength < Dtls13MinimumRecordLength(ssl))
12311242
return BUFFER_ERROR;
12321243

12331244
seqLength = (*hdr & DTLS13_LEN_BIT) ? DTLS13_SEQ_16_LEN : DTLS13_SEQ_8_LEN;
@@ -1453,17 +1464,24 @@ int Dtls13ParseUnifiedRecordLayer(WOLFSSL* ssl, const byte* input,
14531464
hdrInfo->recordLength = inputSize - idx;
14541465
}
14551466

1456-
/* minimum size for a dtls1.3 packet is 16 bytes (to have enough ciphertext
1457-
to create record number xor mask). (draft 43 - Sec 4.2.3) */
1458-
if (hdrInfo->recordLength < DTLS13_RN_MASK_SIZE)
1459-
return LENGTH_ERROR;
1460-
if (inputSize < idx + DTLS13_RN_MASK_SIZE)
1461-
return BUFFER_ERROR;
1467+
#ifdef HAVE_NULL_CIPHER
1468+
/* Do not encrypt record numbers with null cipher. See RFC 9150 Sec 9 */
1469+
if (ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null)
1470+
#endif /*HAVE_NULL_CIPHER */
1471+
{
1472+
/* minimum size for a dtls1.3 packet is 16 bytes (to have enough
1473+
* ciphertext to create record number xor mask).
1474+
* (draft 43 - Sec 4.2.3) */
1475+
if (hdrInfo->recordLength < DTLS13_RN_MASK_SIZE)
1476+
return LENGTH_ERROR;
1477+
if (inputSize < idx + DTLS13_RN_MASK_SIZE)
1478+
return BUFFER_ERROR;
14621479

1463-
ret = Dtls13EncryptDecryptRecordNumber(ssl, seqNum, seqLen, input + idx,
1464-
DEPROTECT);
1465-
if (ret != 0)
1466-
return ret;
1480+
ret = Dtls13EncryptDecryptRecordNumber(ssl, seqNum, seqLen, input + idx,
1481+
DEPROTECT);
1482+
if (ret != 0)
1483+
return ret;
1484+
}
14671485

14681486
if (seqLen == DTLS13_SEQ_16_LEN) {
14691487
hdrInfo->seqHiPresent = 1;

src/tls13.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3199,6 +3199,7 @@ typedef struct BuildMsg13Args {
31993199
word32 idx;
32003200
word32 headerSz;
32013201
word16 size;
3202+
word32 paddingSz;
32023203
} BuildMsg13Args;
32033204

32043205
static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs)
@@ -3304,7 +3305,14 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
33043305
args->sz++;
33053306
/* Authentication data at the end. */
33063307
args->sz += ssl->specs.aead_mac_size;
3307-
3308+
#ifdef WOLFSSL_DTLS13
3309+
/* Pad to minimum length */
3310+
if (ssl->options.dtls &&
3311+
args->sz < (word32)Dtls13MinimumRecordLength(ssl)) {
3312+
args->paddingSz = Dtls13MinimumRecordLength(ssl) - args->sz;
3313+
args->sz = Dtls13MinimumRecordLength(ssl);
3314+
}
3315+
#endif
33083316
if (sizeOnly)
33093317
return (int)args->sz;
33103318

@@ -3348,6 +3356,9 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
33483356

33493357
/* The real record content type goes at the end of the data. */
33503358
output[args->idx++] = (byte)type;
3359+
/* Double check that any necessary padding is zero'd out */
3360+
XMEMSET(output + args->idx, 0, args->paddingSz);
3361+
args->idx += args->paddingSz;
33513362

33523363
ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
33533364
}
@@ -3393,7 +3404,8 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
33933404
#ifdef WOLFSSL_DTLS13
33943405
if (ret == 0 && ssl->options.dtls) {
33953406
/* AAD points to the header. Reuse the variable */
3396-
ret = Dtls13EncryptRecordNumber(ssl, (byte*)aad, (word16)args->sz);
3407+
ret = Dtls13EncryptRecordNumber(ssl, (byte*)aad,
3408+
(word16)args->sz);
33973409
}
33983410
#endif /* WOLFSSL_DTLS13 */
33993411
}

wolfssl/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6828,6 +6828,7 @@ WOLFSSL_LOCAL int Dtls13RlAddCiphertextHeader(WOLFSSL* ssl, byte* out,
68286828
word16 length);
68296829
WOLFSSL_LOCAL int Dtls13RlAddPlaintextHeader(WOLFSSL* ssl, byte* out,
68306830
enum ContentType content_type, word16 length);
6831+
WOLFSSL_LOCAL int Dtls13MinimumRecordLength(WOLFSSL* ssl);
68316832
WOLFSSL_LOCAL int Dtls13EncryptRecordNumber(WOLFSSL* ssl, byte* hdr,
68326833
word16 recordLength);
68336834
WOLFSSL_LOCAL int Dtls13IsUnifiedHeader(byte header_flags);

0 commit comments

Comments
 (0)