Add |SSL_CTX_set0_buffer_pool|.
This currently only works for certificates parsed from the network, but
if making several connections that share certificates, some KB of memory
might be saved.
Change-Id: I0ea4589d7a8b5c41df225ad7f282b6d1376a8db4
Reviewed-on: https://boringssl-review.googlesource.com/12164
Reviewed-by: Adam Langley <alangley@gmail.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 165dca1..689fa82 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -730,6 +730,16 @@
* modes enabled for |ssl|. */
OPENSSL_EXPORT uint32_t SSL_get_mode(const SSL *ssl);
+/* SSL_CTX_set0_buffer_pool sets a |CRYPTO_BUFFER_POOL| that will be used to
+ * store certificates. This can allow multiple connections to share
+ * certificates and thus save memory.
+ *
+ * The SSL_CTX does not take ownership of |pool| and the caller must ensure
+ * that |pool| outlives |ctx| and all objects linked to it, including |SSL|,
+ * |X509| and |SSL_SESSION| objects. Basically, don't ever free |pool|. */
+OPENSSL_EXPORT void SSL_CTX_set0_buffer_pool(SSL_CTX *ctx,
+ CRYPTO_BUFFER_POOL *pool);
+
/* Configuring certificates and private keys.
*
@@ -4073,6 +4083,10 @@
* TODO(agl): remove once node.js no longer references this. */
STACK_OF(X509)* extra_certs;
int freelist_max_len;
+
+ /* pool is used for all |CRYPTO_BUFFER|s in case we wish to share certificate
+ * memory. */
+ CRYPTO_BUFFER_POOL *pool;
};
typedef struct ssl_handshake_st SSL_HANDSHAKE;
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 39c52ed..a984e8e 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -685,6 +685,7 @@
}
if (has_peer) {
+ /* TODO(agl): this should use the |SSL_CTX|'s pool. */
CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, NULL);
if (buffer == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
@@ -719,6 +720,7 @@
}
}
+ /* TODO(agl): this should use the |SSL_CTX|'s pool. */
CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, NULL);
if (buffer == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 1ddf69a..4297245 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -481,7 +481,8 @@
SHA256(CBS_data(&certificate), CBS_len(&certificate), out_leaf_sha256);
}
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&certificate, NULL);
+ CRYPTO_BUFFER *buffer =
+ CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool);
if (buffer == NULL) {
*out_alert = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index ac5a7dd..ad4d1b2 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1080,6 +1080,10 @@
uint32_t SSL_get_mode(const SSL *ssl) { return ssl->mode; }
+void SSL_CTX_set0_buffer_pool(SSL_CTX *ctx, CRYPTO_BUFFER_POOL *pool) {
+ ctx->pool = pool;
+}
+
X509 *SSL_get_peer_certificate(const SSL *ssl) {
if (ssl == NULL) {
return NULL;
diff --git a/ssl/tls13_both.c b/ssl/tls13_both.c
index 8639089..85d804f 100644
--- a/ssl/tls13_both.c
+++ b/ssl/tls13_both.c
@@ -207,7 +207,8 @@
ssl->s3->new_session->peer_sha256);
}
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&certificate, NULL);
+ CRYPTO_BUFFER *buffer =
+ CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool);
if (buffer == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);