Commit a58eb06d authored by Todd Short's avatar Todd Short Committed by Rich Salz
Browse files

Add support to free/allocate SSL buffers



OpenSSL already has the feature of SSL_MODE_RELEASE_BUFFERS that can
be set to release the read or write buffers when data has finished
reading or writing. OpenSSL will automatically re-allocate the buffers
as needed. This can be quite aggressive in terms of memory allocation.

This provides a manual mechanism. SSL_free_buffers() will free
the data buffers if there's no pending data. SSL_alloc_buffers()
will realloc them; but this function is not strictly necessary, as it's
still done automatically in the state machine.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2240)
parent 0a345252
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
=pod

=head1 NAME

SSL_free_buffers, SSL_alloc_buffers - manage SSL structure buffers

=head1 SYNOPSIS

 #include <openssl/ssl.h>

 int SSL_free_buffers(SSL *ssl);
 int SSL_alloc_buffers(SSL *ssl);

=head1 DESCRIPTION

SSL_free_buffers() frees the read and write buffers of the given B<ssl>.
SSL_alloc_buffers() allocates the read and write buffers of the given B<ssl>.

The B<SSL_MODE_RELEASE_BUFFERS> mode releases read or write buffers whenever
the buffers have been drained. These functions allow applications to manually
control when buffers are freed and allocated.

After freeing the buffers, the buffers are automatically reallocted upon a
new read or write. The SSL_alloc_buffers() does not need to be called, but
can be used to make sure the buffers are pre-allocated. This can be used to
avoid allocation during data processing or with CRYPTO_set_mem_functions()
to control where and how buffers are allocated.

=head1 RETURN VALUES

The following return values can occur:

=over 4

=item 0 (Failure)

The SSL_free_buffers() function returns 0 when there is pending data to be
read or written. The SSL_alloc_buffers() function returns 0 when there is
an allocation failure.

=item 1 (Success)

The SSL_free_buffers() function returns 1 if the buffers have been freed. This
value is also returned if the buffers had been freed before calling
SSL_free_buffers().
The SSL_alloc_buffers() function returns 1 if the buffers have been allocated.
This valus is also returned if the buffers had been allocated before calling
SSL_alloc_buffers().

=back

=head1 SEE ALSO

L<SSL_free(3)>, L<SSL_clear(3)>,
L<SSL_new(3)>, L<SSL_CTX_set_mode(3)>,
L<CRYPTO_set_mem_functions>

=head1 COPYRIGHT

Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the OpenSSL license (the "License").  You may not use
this file except in compliance with the License.  You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.

=cut
+4 −2
Original line number Diff line number Diff line
@@ -442,8 +442,7 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U
/*
 * Save RAM by releasing read and write buffers when they're empty. (SSL3 and
 * TLS only.) "Released" buffers are put onto a free-list in the context or
 * just freed (depending on the context's setting for freelist_max_len).
 * TLS only.) Released buffers are freed.
 */
# define SSL_MODE_RELEASE_BUFFERS 0x00000010U
/*
@@ -2238,6 +2237,9 @@ int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
__owur const struct openssl_ssl_test_functions *SSL_test_functions(void);
# endif

__owur int SSL_free_buffers(SSL *ssl);
__owur int SSL_alloc_buffers(SSL *ssl);

extern const char SSL_version_str[];

int ERR_load_SSL_strings(void);
+16 −0
Original line number Diff line number Diff line
@@ -4778,6 +4778,22 @@ int SSL_early_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
    return 0;
}

int SSL_free_buffers(SSL *ssl)
{
    RECORD_LAYER *rl = &ssl->rlayer;

    if (RECORD_LAYER_read_pending(rl) || RECORD_LAYER_write_pending(rl))
        return 0;

    RECORD_LAYER_release(rl);
    return 1;
}

int SSL_alloc_buffers(SSL *ssl)
{
    return ssl3_setup_buffers(ssl);
}

void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb)
{
    ctx->keylog_callback = cb;
+5 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
          bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \
          pkey_meth_test uitest cipherbytes_test asn1_encode_test \
          x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
          recordlentest drbgtest \
          recordlentest drbgtest sslbuffertest \
          time_offset_test pemtest ssl_cert_table_internal_test ciphername_test

  SOURCE[aborttest]=aborttest.c
@@ -437,6 +437,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
    INCLUDE[tls13secretstest]=.. ../include
    DEPEND[tls13secretstest]=../libcrypto ../libssl libtestutil.a
  ENDIF

  SOURCE[sslbuffertest]=sslbuffertest.c ssltestlib.c
  INCLUDE[sslbuffertest]=../include
  DEPEND[sslbuffertest]=../libcrypto ../libssl libtestutil.a
ENDIF

{-
+21 −0
Original line number Diff line number Diff line
#! /usr/bin/env perl
# Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html


use OpenSSL::Test::Utils;
use OpenSSL::Test qw/:DEFAULT srctop_file/;

setup("test_sslbuffers");

plan skip_all => "No suitable TLS/SSL protocol is supported by this OpenSSL build"
    if alldisabled(available_protocols("tls"));

plan tests => 1;

ok(run(test(["sslbuffertest", srctop_file("apps", "server.pem"),
             srctop_file("apps", "server.pem")])), "running sslbuffertest");
Loading