Make sure we call get_max_records() in the record layer code
authorMatt Caswell <matt@openssl.org>
Wed, 31 Aug 2022 20:03:22 +0000 (21:03 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 23 Sep 2022 13:54:49 +0000 (14:54 +0100)
We use the returned data to decide how to split the data we want to write
into records.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19198)

ssl/record/methods/recmethod_local.h
ssl/record/methods/tls_common.c
ssl/record/rec_layer_s3.c
ssl/record/recordmethod.h

index 850c7ae8fa66c59b2cbf4e873e5d0efd3e82d5ad..7c094b3a1618863b865292dd64a6e906902b504a 100644 (file)
@@ -294,7 +294,8 @@ int tls_processed_read_pending(OSSL_RECORD_LAYER *rl);
 size_t tls_app_data_pending(OSSL_RECORD_LAYER *rl);
 int tls_write_pending(OSSL_RECORD_LAYER *rl);
 size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl);
-size_t tls_get_max_records(OSSL_RECORD_LAYER *rl);
+size_t tls_get_max_records(OSSL_RECORD_LAYER *rl, int type, size_t buflen,
+                           size_t maxfrag, size_t *preffrag);
 int tls_write_records(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates,
                       size_t numtempl);
 int tls_retry_write_records(OSSL_RECORD_LAYER *rl);
index 5fb5f4ebbcd25c92e49d1a4390a0cf793a3f7753..32e26008006b290754aa9ee1604875a094ffbb36 100644 (file)
@@ -1408,9 +1408,10 @@ size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl)
     return 0;
 }
 
-size_t tls_get_max_records(OSSL_RECORD_LAYER *rl)
+size_t tls_get_max_records(OSSL_RECORD_LAYER *rl, int type, size_t buflen,
+                           size_t maxfrag, size_t *preffrag)
 {
-    return 0;
+    return 1;
 }
 
 int tls_write_records(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates,
index 0c70995312a09ea6a40f48507a6247fcde894f00..9f81a9f04665e3c2f2a9e548120700228d043e71 100644 (file)
@@ -448,19 +448,17 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
      * processing then we also only use 1 pipeline, or if we're not using
      * explicit IVs
      */
-    maxpipes = s->max_pipelines;
-    if (maxpipes > SSL_MAX_PIPELINES) {
-        /*
-         * We should have prevented this when we set max_pipelines so we
-         * shouldn't get here
-         */
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-        return -1;
-    }
-    /* If no explicit maxpipes configuration - default to 1 */
-    /* TODO(RECLAYER): Should we ask the record layer how many pipes it supports? */
-    if (maxpipes <= 0)
-        maxpipes = 1;
+
+    maxpipes = s->rlayer.wrlmethod->get_max_records(s->rlayer.wrl, type, n,
+                                                    max_send_fragment,
+                                                    &split_send_fragment);
+    if (s->max_pipelines > 0 && maxpipes > s->max_pipelines)
+        maxpipes = s->max_pipelines;
+
+    if (maxpipes > SSL_MAX_PIPELINES)
+        maxpipes = SSL_MAX_PIPELINES;
+
+
 #if 0
     /* TODO(RECLAYER): FIX ME */
     if (maxpipes == 0
@@ -504,7 +502,7 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
         if (numpipes > maxpipes)
             numpipes = maxpipes;
 
-        if (n / numpipes >= max_send_fragment) {
+        if (n / numpipes >= split_send_fragment) {
             /*
              * We have enough data to completely fill all available
              * pipelines
@@ -512,11 +510,11 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
             for (j = 0; j < numpipes; j++) {
                 tmpls[j].type = type;
                 tmpls[j].version = recversion;
-                tmpls[j].buf = &(buf[tot]) + (j * max_send_fragment);
-                tmpls[j].buflen = max_send_fragment;
+                tmpls[j].buf = &(buf[tot]) + (j * split_send_fragment);
+                tmpls[j].buflen = split_send_fragment;
             }
             /* Remember how much data we are going to be sending */
-            s->rlayer.wpend_tot = numpipes * max_send_fragment;
+            s->rlayer.wpend_tot = numpipes * split_send_fragment;
         } else {
             /* We can partially fill all available pipelines */
             tmppipelen = n / numpipes;
index 887a834eb9bc9a207b2cb3bb449cf9a74ff265a2..dad086ea817bad0a3c4358cff75f28e2d9b412d2 100644 (file)
@@ -178,9 +178,17 @@ struct ossl_record_method_st {
      * Find out the maximum number of records that the record layer is prepared
      * to process in a single call to write_records. It is the caller's
      * responsibility to ensure that no call to write_records exceeds this
-     * number of records.
+     * number of records. |type| is the type of the records that the caller
+     * wants to write, and |buflen| is the total amount of data that it wants
+     * to send. |maxfrag| is the maximum allowed fragment size based on user
+     * configuration, or TLS parameter negotiation. |*preffrag| contains on
+     * entry the default fragment size that will actually be used based on user
+     * configuration. This will always be less than or equal to |maxfrag|. On
+     * exit the record layer may update this to an alternative fragment size to
+     * be used. This must always be less than or equal to |maxfrag|.
      */
-    size_t (*get_max_records)(OSSL_RECORD_LAYER *rl);
+    size_t (*get_max_records)(OSSL_RECORD_LAYER *rl, int type, size_t buflen,
+                              size_t maxfrag, size_t *preffrag);
 
     /*
      * Write |numtempl| records from the array of record templates pointed to