Add an ability to set the SSL read buffer size
authorMatt Caswell <matt@openssl.org>
Wed, 13 Jan 2016 14:20:25 +0000 (14:20 +0000)
committerMatt Caswell <matt@openssl.org>
Mon, 7 Mar 2016 21:39:27 +0000 (21:39 +0000)
This capability is required for read pipelining. We will only read in as
many records as will fit in the read buffer (and the network can provide
in one go). The bigger the buffer the more records we can process in
parallel.

Reviewed-by: Tim Hudson <tjh@openssl.org>
apps/s_client.c
apps/s_server.c
include/openssl/ssl.h
ssl/record/rec_layer_s3.c
ssl/record/record.h
ssl/record/record_locl.h
ssl/record/ssl3_buffer.c
ssl/ssl_lib.c
ssl/ssl_locl.h
util/libssl.num

index c6af2936d043e45593033298457e40c2e0e54856..27c8be86a1c3d6503007d8cb293d50f8c3f81110 100644 (file)
@@ -656,7 +656,7 @@ typedef enum OPTION_choice {
     OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN,
     OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME,
     OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_SMTPHOST,
-    OPT_ASYNC, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES,
+    OPT_ASYNC, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
     OPT_V_ENUM,
     OPT_X_ENUM,
     OPT_S_ENUM,
@@ -766,6 +766,8 @@ OPTIONS s_client_options[] = {
      "Size used to split data for encrypt/decrypt pipelines"},
     {"max_pipelines", OPT_MAX_PIPELINES, 'n',
      "Maximum number of encrypt/decrypt pipelines to be used"},
+    {"read_buf", OPT_READ_BUF, 'n',
+     "Default read buffer size to be used for connections"},
     OPT_S_OPTIONS,
     OPT_V_OPTIONS,
     OPT_X_OPTIONS,
@@ -896,6 +898,7 @@ int s_client_main(int argc, char **argv)
     int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM;
     int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0;
     int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
+    int read_buf_len = 0;
     int fallback_scsv = 0;
     long socket_mtu = 0, randamt = 0;
     OPTION_CHOICE o;
@@ -1393,6 +1396,9 @@ int s_client_main(int argc, char **argv)
         case OPT_MAX_PIPELINES:
             max_pipelines = atoi(opt_arg());
             break;
+        case OPT_READ_BUF:
+            read_buf_len = atoi(opt_arg());
+            break;
         }
     }
     argc = opt_num_rest();
@@ -1573,6 +1579,10 @@ int s_client_main(int argc, char **argv)
         SSL_CTX_set_max_pipelines(ctx, max_pipelines);
     }
 
+    if (read_buf_len > 0) {
+        SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
+    }
+
     if (!config_ctx(cctx, ssl_args, ctx))
         goto end;
 
index f544be15961c5a04a95879763db4283d81313819..22e917542b3a5d673c681912d601cdbb153c9230 100644 (file)
@@ -809,8 +809,8 @@ typedef enum OPTION_choice {
     OPT_QUIET, OPT_BRIEF, OPT_NO_DHE,
     OPT_NO_RESUME_EPHEMERAL, OPT_PSK_HINT, OPT_PSK, OPT_SRPVFILE,
     OPT_SRPUSERSEED, OPT_REV, OPT_WWW, OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC,
-    OPT_SSL_CONFIG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_SSL3,
-    OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
+    OPT_SSL_CONFIG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
+    OPT_SSL3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
     OPT_DTLS1_2, OPT_TIMEOUT, OPT_MTU, OPT_CHAIN, OPT_LISTEN,
     OPT_ID_PREFIX, OPT_RAND, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
     OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
@@ -946,6 +946,8 @@ OPTIONS s_server_options[] = {
      "Size used to split data for encrypt/decrypt pipelines"},
     {"max_pipelines", OPT_MAX_PIPELINES, 'n',
      "Maximum number of encrypt/decrypt pipelines to be used"},
+    {"read_buf", OPT_READ_BUF, 'n',
+     "Default read buffer size to be used for connections"},
     OPT_S_OPTIONS,
     OPT_V_OPTIONS,
     OPT_X_OPTIONS,
@@ -1049,6 +1051,7 @@ int s_server_main(int argc, char *argv[])
     X509 *s_cert2 = NULL;
     tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING };
     const char *ssl_config = NULL;
+    int read_buf_len = 0;
 #ifndef OPENSSL_NO_NEXTPROTONEG
     const char *next_proto_neg_in = NULL;
     tlsextnextprotoctx next_proto = { NULL, 0 };
@@ -1521,6 +1524,10 @@ int s_server_main(int argc, char *argv[])
         case OPT_MAX_PIPELINES:
             max_pipelines = atoi(opt_arg());
             break;
+        case OPT_READ_BUF:
+            read_buf_len = atoi(opt_arg());
+            break;
+
         }
     }
     argc = opt_num_rest();
@@ -1753,6 +1760,10 @@ int s_server_main(int argc, char *argv[])
         SSL_CTX_set_max_pipelines(ctx, max_pipelines);
     }
 
+    if (read_buf_len > 0) {
+        SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
+    }
+
 #ifndef OPENSSL_NO_SRTP
     if (srtp_profiles != NULL) {
         /* Returns 0 on success! */
index 43d59a623b10bf41a45f29b686dce05d02a304d2..94ea5ee17a10d956567f16e7ca09ceb1aa76b89f 100644 (file)
@@ -1808,6 +1808,9 @@ __owur int SSL_get_ex_data_X509_STORE_CTX_idx(void);
 # define SSL_set_max_pipelines(ssl,m) \
         SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
 
+void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
+void SSL_set_default_read_buffer_len(SSL *s, size_t len);
+
      /* NB: the keylength is only applicable when is_export is true */
 # ifndef OPENSSL_NO_DH
 void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
index 91b8205ee99167177d06b12756b83d2536824142..83f5cf56db91072b623b4c11ce30dadb195725ba 100644 (file)
@@ -241,6 +241,16 @@ int ssl3_pending(const SSL *s)
     return num;
 }
 
+void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len)
+{
+    ctx->default_read_buf_len = len;
+}
+
+void SSL_set_default_read_buffer_len(SSL *s, size_t len)
+{
+    SSL3_BUFFER_set_default_len(RECORD_LAYER_get_rbuf(&s->rlayer), len);
+}
+
 const char *SSL_rstate_string_long(const SSL *s)
 {
     const char *str;
index 000fc856212685be239da193d97705f536ed089e..a1febc55514481aaa62ec2168dd61d48655e0597 100644 (file)
 typedef struct ssl3_buffer_st {
     /* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */
     unsigned char *buf;
+    /* default buffer size (or 0 if no default set) */
+    size_t default_len;
     /* buffer size */
     size_t len;
     /* where to 'copy from' */
index e5d2784f262a11e9835c6224fa51fa4622700a54..f1f5bbcbcce22f0edf180b4accdbb670368be0b9 100644 (file)
@@ -162,6 +162,7 @@ void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
 #define SSL3_BUFFER_set_offset(b, o)        ((b)->offset = (o))
 #define SSL3_BUFFER_add_offset(b, o)        ((b)->offset += (o))
 #define SSL3_BUFFER_is_initialised(b)       ((b)->buf != NULL)
+#define SSL3_BUFFER_set_default_len(b, l)   ((b)->default_len = (l))
 
 void SSL3_BUFFER_clear(SSL3_BUFFER *b);
 void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n);
index 576533c31ee9c46087d167829a84dc0cf1df4dc1..53ae0f490d80b72fb2a19bae24708e9bc1062824 100644 (file)
@@ -120,16 +120,13 @@ void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n)
 }
 
 /*
- * Clear the contents of an SSL3_BUFFER but retain any memory allocated
+ * Clear the contents of an SSL3_BUFFER but retain any memory allocated. Also
+ * retains the default_len setting
  */
 void SSL3_BUFFER_clear(SSL3_BUFFER *b)
 {
-    unsigned char *buf = b->buf;
-    size_t len = b->len;
-
-    memset(b, 0, sizeof(*b));
-    b->buf = buf;
-    b->len = len;
+    b->offset = 0;
+    b->left = 0;
 }
 
 void SSL3_BUFFER_release(SSL3_BUFFER *b)
@@ -162,6 +159,8 @@ int ssl3_setup_read_buffer(SSL *s)
         if (ssl_allow_compression(s))
             len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
 #endif
+        if (b->default_len > len)
+            len = b->default_len;
         if ((p = OPENSSL_malloc(len)) == NULL)
             goto err;
         b->buf = p;
index 92734ea937288b29f61824cf7a0d605ef7c4e6d0..4df83399791c956ef36ef1dcb46d06468d3b26c8 100644 (file)
@@ -674,6 +674,8 @@ SSL *SSL_new(SSL_CTX *ctx)
     s->max_pipelines = ctx->max_pipelines;
     if (s->max_pipelines > 1)
         RECORD_LAYER_set_read_ahead(&s->rlayer, 1);
+    if (ctx->default_read_buf_len > 0)
+        SSL_set_default_read_buffer_len(s, ctx->default_read_buf_len);
 
     CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
     s->ctx = ctx;
index aa3e0a307edf7d37c65978751fb1778f9864832d..064c22c25abdd0535b814d615a727cfab23641f4 100644 (file)
@@ -843,6 +843,9 @@ struct ssl_ctx_st {
     /* Up to how many pipelines should we use? If 0 then 1 is assumed */
     unsigned int max_pipelines;
 
+    /* The default read buffer length to use (0 means not set) */
+    size_t default_read_buf_len;
+
 #  ifndef OPENSSL_NO_ENGINE
     /*
      * Engine to pass requests for client certs to
index f1f2dd198c8c1fff712f21ae99944860a9b9c182..3ba959dc56408af4493d061f8c986e06440496cc 100644 (file)
@@ -381,3 +381,5 @@ SSL_get_ct_validation_callback          380 1_1_0   EXIST::FUNCTION:CT
 SSL_get0_peer_scts                      381    1_1_0   EXIST::FUNCTION:CT
 SSL_CTX_set_ct_validation_callback      382    1_1_0   EXIST::FUNCTION:CT
 SSL_CTX_get_ct_validation_callback      383    1_1_0   EXIST::FUNCTION:CT
+SSL_set_default_read_buffer_len         384    1_1_0   EXIST::FUNCTION:
+SSL_CTX_set_default_read_buffer_len     385    1_1_0   EXIST::FUNCTION: