Loading CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,10 @@ Changes between 0.9.8g and 0.9.9 [xx XXX xxxx] *) Add a new SSL_MODE_RELEASE_BUFFERS mode flag to release unused buffer RAM on SSL connections. This option can save about 34k per idle SSL. [Nick Mathewson] *) Expand ENGINE to support engine supplied SSL client certificate functions. [Steve Henson] Loading doc/ssl/SSL_CTX_set_mode.pod +10 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,16 @@ deal with read/write operations returning without success report. The flag SSL_MODE_AUTO_RETRY will cause read/write operations to only return after the handshake and successful completion. =item SSL_MODE_RELEASE_BUFFERS When we no longer need a read buffer or a write buffer for a given SSL, then release the memory we were using to hold it. Released memory is either appended to a list of unused RAM chunks on the SSL_CTX, or simply freed if the list of unused chunks would become longer than SSL_CTX->freelist_max_len, which defaults to 32. Using this flag can save around 34k per idle SSL connection. This flag has no effect on SSL v2 connections, or on DTLS connections. =back =head1 RETURN VALUES Loading ssl/s23_clnt.c +3 −0 Original line number Diff line number Diff line Loading @@ -640,6 +640,9 @@ static int ssl23_get_server_hello(SSL *s) * for SSLv3 */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; if (s->s3->rbuf.buf == NULL) if (!ssl3_setup_read_buffer(s)) goto err; s->packet= &(s->s3->rbuf.buf[0]); memcpy(s->packet,buf,n); s->s3->rbuf.left=n; Loading ssl/s23_srvr.c +4 −0 Original line number Diff line number Diff line Loading @@ -545,6 +545,10 @@ int ssl23_get_client_hello(SSL *s) * for SSLv3 */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; if (s->s3->rbuf.buf == NULL) if (!ssl3_setup_read_buffer(s)) goto err; s->packet= &(s->s3->rbuf.buf[0]); memcpy(s->packet,buf,n); s->s3->rbuf.left=n; Loading ssl/s3_both.c +130 −6 Original line number Diff line number Diff line Loading @@ -591,7 +591,81 @@ int ssl_verify_alarm_type(long type) return(al); } int ssl3_setup_buffers(SSL *s) #if !defined(OPENSSL_NO_BUF_FREELISTS) && !defined(OPENSSL_NO_RELEASE_BUFFERS) /* On some platforms, malloc() performance is bad enough that you can't just * free() and malloc() buffers all the time, so we need to use freelists from * unused buffers. Currently, each freelist holds memory chunks of only a * given size (list->chunklen); other sized chunks are freed and malloced. * This doesn't help much if you're using many different SSL option settings * with a given context. (The options affecting buffer size are * max_send_fragment, read buffer vs write buffer, * SSL_OP_MICROSOFT_BIG_WRITE_BUFFER, SSL_OP_NO_COMPRESSION, and * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS.) Using a separate freelist for every * possible size is not an option, since max_send_fragment can take on many * different values. * * If you are on a platform with a slow malloc(), and you're using SSL * connections with many different settings for these options, and you need to * use the SSL_MOD_RELEASE_BUFFERS feature, you have a few options: * - Link against a faster malloc implementation. * - Use a separate SSL_CTX for each option set. * - Improve this code. */ static void * freelist_extract(SSL_CTX *ctx, int for_read, int sz) { SSL3_BUF_FREELIST *list; SSL3_BUF_FREELIST_ENTRY *ent = NULL; void *result = NULL; CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist; if (list != NULL && sz == list->chunklen) ent = list->head; if (ent != NULL) { list->head = ent->next; result = ent; if (--list->len == 0) list->chunklen = 0; } CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); if (!result) result = OPENSSL_malloc(sz); return result; } static void freelist_insert(SSL_CTX *ctx, int for_read, size_t sz, void *mem) { SSL3_BUF_FREELIST *list; SSL3_BUF_FREELIST_ENTRY *ent; CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist; if (list != NULL && (sz == list->chunklen || list->chunklen == 0) && list->len < ctx->freelist_max_len && sz >= sizeof(*ent)) { list->chunklen = sz; ent = mem; ent->next = list->head; list->head = ent; ++list->len; mem = NULL; } CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); if (mem) OPENSSL_free(mem); } #else #define freelist_extract(c,fr,sz) OPENSSL_malloc(sz) #define freelist_insert(c,fr,sz,m) OPENSSL_free(m) #endif int ssl3_setup_read_buffer(SSL *s) { unsigned char *p; size_t len,align=0; Loading @@ -614,12 +688,29 @@ int ssl3_setup_buffers(SSL *s) if (!(s->options & SSL_OP_NO_COMPRESSION)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if ((p=OPENSSL_malloc(len)) == NULL) if ((p=freelist_extract(s->ctx, 1, len)) == NULL) goto err; s->s3->rbuf.buf = p; s->s3->rbuf.len = len; } s->packet= &(s->s3->rbuf.buf[0]); return 1; err: SSLerr(SSL_F_SSL3_SETUP_BUFFERS,ERR_R_MALLOC_FAILURE); return 0; } int ssl3_setup_write_buffer(SSL *s) { unsigned char *p; size_t len,align=0; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1); #endif if (s->s3->wbuf.buf == NULL) { len = s->max_send_fragment Loading @@ -632,14 +723,47 @@ int ssl3_setup_buffers(SSL *s) if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) len += SSL3_RT_HEADER_LENGTH + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; if ((p=OPENSSL_malloc(len)) == NULL) if ((p=freelist_extract(s->ctx, 0, len)) == NULL) goto err; s->s3->wbuf.buf = p; s->s3->wbuf.len = len; } s->packet= &(s->s3->rbuf.buf[0]); return(1); return 1; err: SSLerr(SSL_F_SSL3_SETUP_BUFFERS,ERR_R_MALLOC_FAILURE); return(0); return 0; } int ssl3_setup_buffers(SSL *s) { if (!ssl3_setup_read_buffer(s)) return 0; if (!ssl3_setup_write_buffer(s)) return 0; return 1; } int ssl3_release_write_buffer(SSL *s) { if (s->s3->wbuf.buf != NULL) { freelist_insert(s->ctx, 0, s->s3->wbuf.len, s->s3->wbuf.buf); s->s3->wbuf.buf = NULL; } return 1; } int ssl3_release_read_buffer(SSL *s) { if (s->s3->rbuf.buf != NULL) { freelist_insert(s->ctx, 1, s->s3->rbuf.len, s->s3->rbuf.buf); s->s3->rbuf.buf = NULL; } return 1; } Loading
CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,10 @@ Changes between 0.9.8g and 0.9.9 [xx XXX xxxx] *) Add a new SSL_MODE_RELEASE_BUFFERS mode flag to release unused buffer RAM on SSL connections. This option can save about 34k per idle SSL. [Nick Mathewson] *) Expand ENGINE to support engine supplied SSL client certificate functions. [Steve Henson] Loading
doc/ssl/SSL_CTX_set_mode.pod +10 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,16 @@ deal with read/write operations returning without success report. The flag SSL_MODE_AUTO_RETRY will cause read/write operations to only return after the handshake and successful completion. =item SSL_MODE_RELEASE_BUFFERS When we no longer need a read buffer or a write buffer for a given SSL, then release the memory we were using to hold it. Released memory is either appended to a list of unused RAM chunks on the SSL_CTX, or simply freed if the list of unused chunks would become longer than SSL_CTX->freelist_max_len, which defaults to 32. Using this flag can save around 34k per idle SSL connection. This flag has no effect on SSL v2 connections, or on DTLS connections. =back =head1 RETURN VALUES Loading
ssl/s23_clnt.c +3 −0 Original line number Diff line number Diff line Loading @@ -640,6 +640,9 @@ static int ssl23_get_server_hello(SSL *s) * for SSLv3 */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; if (s->s3->rbuf.buf == NULL) if (!ssl3_setup_read_buffer(s)) goto err; s->packet= &(s->s3->rbuf.buf[0]); memcpy(s->packet,buf,n); s->s3->rbuf.left=n; Loading
ssl/s23_srvr.c +4 −0 Original line number Diff line number Diff line Loading @@ -545,6 +545,10 @@ int ssl23_get_client_hello(SSL *s) * for SSLv3 */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; if (s->s3->rbuf.buf == NULL) if (!ssl3_setup_read_buffer(s)) goto err; s->packet= &(s->s3->rbuf.buf[0]); memcpy(s->packet,buf,n); s->s3->rbuf.left=n; Loading
ssl/s3_both.c +130 −6 Original line number Diff line number Diff line Loading @@ -591,7 +591,81 @@ int ssl_verify_alarm_type(long type) return(al); } int ssl3_setup_buffers(SSL *s) #if !defined(OPENSSL_NO_BUF_FREELISTS) && !defined(OPENSSL_NO_RELEASE_BUFFERS) /* On some platforms, malloc() performance is bad enough that you can't just * free() and malloc() buffers all the time, so we need to use freelists from * unused buffers. Currently, each freelist holds memory chunks of only a * given size (list->chunklen); other sized chunks are freed and malloced. * This doesn't help much if you're using many different SSL option settings * with a given context. (The options affecting buffer size are * max_send_fragment, read buffer vs write buffer, * SSL_OP_MICROSOFT_BIG_WRITE_BUFFER, SSL_OP_NO_COMPRESSION, and * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS.) Using a separate freelist for every * possible size is not an option, since max_send_fragment can take on many * different values. * * If you are on a platform with a slow malloc(), and you're using SSL * connections with many different settings for these options, and you need to * use the SSL_MOD_RELEASE_BUFFERS feature, you have a few options: * - Link against a faster malloc implementation. * - Use a separate SSL_CTX for each option set. * - Improve this code. */ static void * freelist_extract(SSL_CTX *ctx, int for_read, int sz) { SSL3_BUF_FREELIST *list; SSL3_BUF_FREELIST_ENTRY *ent = NULL; void *result = NULL; CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist; if (list != NULL && sz == list->chunklen) ent = list->head; if (ent != NULL) { list->head = ent->next; result = ent; if (--list->len == 0) list->chunklen = 0; } CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); if (!result) result = OPENSSL_malloc(sz); return result; } static void freelist_insert(SSL_CTX *ctx, int for_read, size_t sz, void *mem) { SSL3_BUF_FREELIST *list; SSL3_BUF_FREELIST_ENTRY *ent; CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist; if (list != NULL && (sz == list->chunklen || list->chunklen == 0) && list->len < ctx->freelist_max_len && sz >= sizeof(*ent)) { list->chunklen = sz; ent = mem; ent->next = list->head; list->head = ent; ++list->len; mem = NULL; } CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); if (mem) OPENSSL_free(mem); } #else #define freelist_extract(c,fr,sz) OPENSSL_malloc(sz) #define freelist_insert(c,fr,sz,m) OPENSSL_free(m) #endif int ssl3_setup_read_buffer(SSL *s) { unsigned char *p; size_t len,align=0; Loading @@ -614,12 +688,29 @@ int ssl3_setup_buffers(SSL *s) if (!(s->options & SSL_OP_NO_COMPRESSION)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if ((p=OPENSSL_malloc(len)) == NULL) if ((p=freelist_extract(s->ctx, 1, len)) == NULL) goto err; s->s3->rbuf.buf = p; s->s3->rbuf.len = len; } s->packet= &(s->s3->rbuf.buf[0]); return 1; err: SSLerr(SSL_F_SSL3_SETUP_BUFFERS,ERR_R_MALLOC_FAILURE); return 0; } int ssl3_setup_write_buffer(SSL *s) { unsigned char *p; size_t len,align=0; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1); #endif if (s->s3->wbuf.buf == NULL) { len = s->max_send_fragment Loading @@ -632,14 +723,47 @@ int ssl3_setup_buffers(SSL *s) if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) len += SSL3_RT_HEADER_LENGTH + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; if ((p=OPENSSL_malloc(len)) == NULL) if ((p=freelist_extract(s->ctx, 0, len)) == NULL) goto err; s->s3->wbuf.buf = p; s->s3->wbuf.len = len; } s->packet= &(s->s3->rbuf.buf[0]); return(1); return 1; err: SSLerr(SSL_F_SSL3_SETUP_BUFFERS,ERR_R_MALLOC_FAILURE); return(0); return 0; } int ssl3_setup_buffers(SSL *s) { if (!ssl3_setup_read_buffer(s)) return 0; if (!ssl3_setup_write_buffer(s)) return 0; return 1; } int ssl3_release_write_buffer(SSL *s) { if (s->s3->wbuf.buf != NULL) { freelist_insert(s->ctx, 0, s->s3->wbuf.len, s->s3->wbuf.buf); s->s3->wbuf.buf = NULL; } return 1; } int ssl3_release_read_buffer(SSL *s) { if (s->s3->rbuf.buf != NULL) { freelist_insert(s->ctx, 1, s->s3->rbuf.len, s->s3->rbuf.buf); s->s3->rbuf.buf = NULL; } return 1; }