@@ -10759,7 +10759,13 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
1075910759 inputSz += HANDSHAKE_HEADER_SZ;
1076010760 rHdrSz = RECORD_HEADER_SZ;
1076110761 }
10762- maxFrag = wolfSSL_GetMaxFragSize(ssl, (int)inputSz);
10762+ maxFrag = wolfssl_local_GetMaxPlaintextSize(ssl);
10763+ #ifdef WOLFSSL_DTLS
10764+ if (ssl->options.dtls) {
10765+ /* In DTLS the handshake header is per fragment */
10766+ maxFrag -= DTLS_HANDSHAKE_HEADER_SZ;
10767+ }
10768+ #endif
1076310769
1076410770 /* Make sure input is not the ssl output buffer as this
1076510771 * function doesn't handle that */
@@ -24819,9 +24825,12 @@ int SendCertificate(WOLFSSL* ssl)
2481924825 if (ssl->fragOffset != 0)
2482024826 length -= (ssl->fragOffset + headerSz);
2482124827
24822- maxFragment = MAX_RECORD_SIZE;
2482324828
24824- maxFragment = (word32)wolfSSL_GetMaxFragSize(ssl, (int)maxFragment);
24829+ maxFragment = (word32)wolfssl_local_GetMaxPlaintextSize(ssl);
24830+ if (ssl->options.dtls)
24831+ maxFragment -= DTLS_HANDSHAKE_HEADER_SZ;
24832+ else
24833+ maxFragment -= HANDSHAKE_HEADER_SZ;
2482524834
2482624835 while (length > 0 && ret == 0) {
2482724836 byte* output = NULL;
@@ -25598,27 +25607,6 @@ int IsSCR(WOLFSSL* ssl)
2559825607}
2559925608
2560025609
25601- #ifdef WOLFSSL_DTLS
25602- static int ModifyForMTU(WOLFSSL* ssl, int buffSz, int outputSz, int mtuSz)
25603- {
25604- int recordExtra = outputSz - buffSz;
25605-
25606- (void)ssl;
25607-
25608- if (recordExtra > 0 && outputSz > mtuSz) {
25609- buffSz = mtuSz - recordExtra;
25610- #ifndef WOLFSSL_AEAD_ONLY
25611- /* Subtract a block size to be certain that returned fragment
25612- * size won't get more padding. */
25613- if (ssl->specs.cipher_type == block)
25614- buffSz -= ssl->specs.block_size;
25615- #endif
25616- }
25617-
25618- return buffSz;
25619- }
25620- #endif /* WOLFSSL_DTLS */
25621-
2562225610#if !defined(NO_TLS) && defined(WOLFSSL_TLS13) && \
2562325611 !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS)
2562425612/*
@@ -25996,31 +25984,33 @@ int SendData(WOLFSSL* ssl, const void* data, size_t sz)
2599625984 }
2599725985#endif /* WOLFSSL_DTLS13 */
2599825986
25999- buffSz = wolfSSL_GetMaxFragSize(ssl, (word32)sz - sent);
26000-
2600125987 if (sent == (word32)sz) break;
2600225988
26003- #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_DTLS_SIZE_CHECK)
26004- if (ssl->options.dtls && ((size_t)buffSz < (word32)sz - sent)) {
26005- error = DTLS_SIZE_ERROR;
26006- ssl->error = error;
26007- WOLFSSL_ERROR(error);
26008- return error;
26009- }
26010- #endif
26011- outputSz = buffSz + COMP_EXTRA + DTLS_RECORD_HEADER_SZ;
26012- if (IsEncryptionOn(ssl, 1) || ssl->options.tls1_3)
26013- outputSz += cipherExtraData(ssl);
26014-
26015- #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
25989+ buffSz = (word32)sz - sent;
25990+ outputSz = wolfssl_local_GetRecordSize(ssl, (word32)buffSz, 1);
25991+ #if defined(WOLFSSL_DTLS)
2601625992 if (ssl->options.dtls) {
26017- byte cidSz = 0;
26018- if ((cidSz = DtlsGetCidTxSize( ssl)) > 0)
26019- outputSz += cidSz + 1; /* +1 for inner content type */
26020- }
25993+ #if defined(WOLFSSL_DTLS_MTU)
25994+ int mtu = ssl->dtlsMtuSz;
25995+ #else
25996+ int mtu = MAX_MTU;
2602125997#endif
25998+ if (outputSz > mtu) {
25999+ #if defined(WOLFSSL_NO_DTLS_SIZE_CHECK)
26000+ /* split instead of error out */
26001+ buffSz = min(buffSz, wolfssl_local_GetMaxPlaintextSize(ssl));
26002+ outputSz = wolfssl_local_GetRecordSize(ssl, (word32)buffSz, 1);
26003+ #else
26004+ error = DTLS_SIZE_ERROR;
26005+ ssl->error = error;
26006+ WOLFSSL_ERROR(error);
26007+ return error;
26008+ #endif /* WOLFSSL_NO_DTLS_SIZE_CHECK */
26009+ }
26010+ }
26011+ #endif /* WOLFSSL_DTLS */
2602226012
26023- /* check for available size */
26013+ /* check for available size, it does also DTLS MTU checks */
2602426014 if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
2602526015 return (ssl->error = ret);
2602626016
@@ -41838,53 +41828,125 @@ int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev)
4183841828
4183941829#endif /* WOLFSSL_ASYNC_CRYPT */
4184041830
41831+ #if !defined(NO_TLS)
41832+ /** Return the record size for sending payloadSz of data
41833+ * @param ssl WOLFSSL object
41834+ * @param payloadSz Size of data to be sent in record
41835+ * @param isEncrypted 1 if encryption is on, 0 if not
41836+ * @return Record size for sending payloadSz of data
41837+ */
41838+ int wolfssl_local_GetRecordSize(WOLFSSL *ssl, int payloadSz, int isEncrypted)
41839+ {
41840+ int recordSz;
4184141841
41842+ if (ssl == NULL)
41843+ return BAD_FUNC_ARG;
41844+
41845+ if (isEncrypted) {
41846+ recordSz = BuildMessage(ssl, NULL, 0, NULL, payloadSz, application_data,
41847+ 0, 1, 0, CUR_ORDER);
41848+ /* use a safe upper bound in case of error */
41849+ if (recordSz < 0) {
41850+ recordSz = payloadSz + RECORD_HEADER_SZ
41851+ + cipherExtraData(ssl) + COMP_EXTRA;
41852+ if (ssl->options.dtls) {
41853+ recordSz += DTLS_RECORD_EXTRA;
41854+ }
41855+ }
41856+ }
41857+ else {
41858+ recordSz = payloadSz + RECORD_HEADER_SZ;
41859+ if (ssl->options.dtls) {
41860+ recordSz += DTLS_RECORD_EXTRA;
41861+ }
41862+ }
41863+ return recordSz;
41864+ }
41865+ #endif
41866+
41867+ /** Return the maximum plaintext size for the current Max Fragment and MTU.
41868+ * @param ssl WOLFSSL object containing ciphersuite information.
41869+ * @return Max plaintext size for current MTU
41870+ */
41871+ int wolfssl_local_GetMaxPlaintextSize(WOLFSSL *ssl)
41872+ {
41873+ int maxFrag;
41874+
41875+ if (ssl == NULL)
41876+ return BAD_FUNC_ARG;
41877+
41878+ maxFrag = wolfSSL_GetMaxFragSize(ssl);
41879+
41880+ #if defined(WOLFSSL_DTLS)
41881+ if (IsDtlsNotSctpMode(ssl)) {
41882+ int recordSz;
41883+ int mtu;
41884+
41885+ #if defined(WOLFSSL_DTLS_MTU)
41886+ mtu = ssl->dtlsMtuSz;
41887+ #else
41888+ mtu = MAX_MTU;
41889+ #endif
41890+
41891+ recordSz = wolfssl_local_GetRecordSize(ssl, maxFrag,
41892+ IsEncryptionOn(ssl, 1));
41893+ /* record size of maxFrag fits in MTU */
41894+ if (recordSz <= mtu) {
41895+ return maxFrag;
41896+ }
41897+
41898+ /* adjust plaintext size to fit in MTU */
41899+ maxFrag -= (recordSz - mtu);
41900+ if (maxFrag <= 0) {
41901+ WOLFSSL_MSG("MTU too small for any plaintext");
41902+ return DTLS_SIZE_ERROR;
41903+ }
41904+
41905+ #ifndef WOLFSSL_AEAD_ONLY
41906+ /* For block ciphers, reducing maxFrag may change padding alignment,
41907+ * causing the record to still exceed MTU. Iterate to find exact fit.
41908+ * Converges in at most 2 iterations due to bounded padding variance. */
41909+ if (ssl->specs.cipher_type == block) {
41910+ int iter;
41911+ for (iter = 0; iter < 2; iter++) {
41912+ recordSz = wolfssl_local_GetRecordSize(ssl, maxFrag,
41913+ IsEncryptionOn(ssl, 1));
41914+ if (recordSz <= mtu)
41915+ break;
41916+ maxFrag -= (recordSz - mtu);
41917+ }
41918+ if (recordSz > mtu) {
41919+ /* this should never happen */
41920+ WOLFSSL_MSG("Failed to fit record in MTU after padding adjust");
41921+ return DTLS_SIZE_ERROR;
41922+ }
41923+ }
41924+ #endif
41925+ }
41926+ #endif /* WOLFSSL_DTLS */
41927+
41928+ return maxFrag;
41929+ }
4184241930/**
4184341931 * Return the max fragment size. This is essentially the maximum
4184441932 * fragment_length available.
4184541933 * @param ssl WOLFSSL object containing ciphersuite information.
41846- * @param maxFragment The amount of space we want to check is available. This
41847- * is only the fragment length WITHOUT the (D)TLS headers.
4184841934 * @return Max fragment size
4184941935 */
41850- int wolfSSL_GetMaxFragSize(WOLFSSL* ssl, int maxFragment )
41936+ int wolfSSL_GetMaxFragSize(WOLFSSL* ssl)
4185141937{
41852- (void) ssl; /* Avoid compiler warnings */
41938+ int maxFragment;
4185341939
41854- if (maxFragment > MAX_RECORD_SIZE) {
41855- maxFragment = MAX_RECORD_SIZE;
41856- }
41940+ if (ssl == NULL)
41941+ return BAD_FUNC_ARG;
41942+
41943+ maxFragment = MAX_RECORD_SIZE;
4185741944
4185841945#ifdef HAVE_MAX_FRAGMENT
4185941946 if ((ssl->max_fragment != 0) && ((word16)maxFragment > ssl->max_fragment)) {
4186041947 maxFragment = ssl->max_fragment;
4186141948 }
4186241949#endif /* HAVE_MAX_FRAGMENT */
41863- #ifdef WOLFSSL_DTLS
41864- if (IsDtlsNotSctpMode(ssl)) {
41865- int outputSz, mtuSz;
41866-
41867- /* Given a input buffer size of maxFragment, how big will the
41868- * encrypted output be? */
41869- if (IsEncryptionOn(ssl, 1)) {
41870- outputSz = BuildMessage(ssl, NULL, 0, NULL,
41871- maxFragment + DTLS_HANDSHAKE_HEADER_SZ,
41872- application_data, 0, 1, 0, CUR_ORDER);
41873- }
41874- else {
41875- outputSz = maxFragment + DTLS_RECORD_HEADER_SZ +
41876- DTLS_HANDSHAKE_HEADER_SZ;
41877- }
41878-
41879- /* Readjust maxFragment for MTU size. */
41880- #if defined(WOLFSSL_DTLS_MTU)
41881- mtuSz = ssl->dtlsMtuSz;
41882- #else
41883- mtuSz = MAX_MTU;
41884- #endif
41885- maxFragment = ModifyForMTU(ssl, maxFragment, outputSz, mtuSz);
41886- }
41887- #endif
4188841950
4188941951 return maxFragment;
4189041952}
0 commit comments