Don't use the buffer BIO in TLS.
On the TLS side, we introduce a running buffer of ciphertext. Queuing up
pending data consists of encrypting the record into the buffer. This
effectively reimplements what the buffer BIO was doing previously, but
this resizes to fit the whole flight.
As part of this, rename all the functions to add to the pending flight
to be more uniform. This CL proposes "add_foo" to add to the pending
flight and "flush_flight" to drain it.
We add an add_alert hook for alerts but, for now, only the SSL 3.0
warning alert (sent mid-handshake) uses this mechanism. Later work will
push this down to the rest of the write path so closure alerts use it
too, as in DTLS. The intended end state is that all the ssl_buffer.c and
wpend_ret logic will only be used for application data and eventually
optionally replaced by the in-place API, while all "incidental" data
will be handled internally.
For now, the two buffers are mutually exclusive. Moving closure alerts
to "incidentals" will change this, but flushing application data early
is tricky due to wpend_ret. (If we call ssl_write_buffer_flush,
do_ssl3_write doesn't realize it still has a wpend_ret to replay.) That
too is all left alone in this change.
To keep the diff down, write_message is retained for now and will be
removed from the state machines in a follow-up change.
BUG=72
Change-Id: Ibce882f5f7196880648f25d5005322ca4055c71d
Reviewed-on: https://boringssl-review.googlesource.com/13224
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h
index ffe4d62..877822d 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1333,16 +1333,17 @@
* release it with |OPENSSL_free| when done. It returns one on success and
* zero on error. */
int (*finish_message)(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
- /* queue_message queues a handshake message and prepares it to be written. It
- * takes ownership of |msg| and releases it with |OPENSSL_free| when done. It
- * returns one on success and zero on error. */
- int (*queue_message)(SSL *ssl, uint8_t *msg, size_t len);
- /* write_message writes the next message to the transport. It returns one on
- * success and <= 0 on error. */
- int (*write_message)(SSL *ssl);
- /* send_change_cipher_spec sends a ChangeCipherSpec message. */
- int (*send_change_cipher_spec)(SSL *ssl);
- /* flush_flight flushes the current flight to the transport. It returns one on
+ /* add_message adds a handshake message to the pending flight. It returns one
+ * on success and zero on error. In either case, it takes ownership of |msg|
+ * and releases it with |OPENSSL_free| when done. */
+ int (*add_message)(SSL *ssl, uint8_t *msg, size_t len);
+ /* add_change_cipher_spec adds a ChangeCipherSpec record to the pending
+ * flight. It returns one on success and zero on error. */
+ int (*add_change_cipher_spec)(SSL *ssl);
+ /* add_alert adds an alert to the pending flight. It returns one on success
+ * and zero on error. */
+ int (*add_alert)(SSL *ssl, uint8_t level, uint8_t desc);
+ /* flush_flight flushes the pending flight to the transport. It returns one on
* success and <= 0 on error. */
int (*flush_flight)(SSL *ssl);
/* expect_flight is called when the handshake expects a flight of messages from
@@ -1359,6 +1360,8 @@
* ownership of |aead_ctx|. It returns one on success and zero if changing the
* write state is forbidden at this point. */
int (*set_write_state)(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
+ /* write_message returns one. */
+ int (*write_message)(SSL *ssl);
};
/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit
@@ -1491,9 +1494,13 @@
uint8_t send_alert[2];
- /* pending_message is the current outgoing handshake message. */
- uint8_t *pending_message;
- uint32_t pending_message_len;
+ /* pending_flight is the pending outgoing flight. This is used to flush each
+ * handshake flight in a single write. */
+ BUF_MEM *pending_flight;
+
+ /* pending_flight_offset is the number of bytes of |pending_flight| which have
+ * been successfully written. */
+ uint32_t pending_flight_offset;
/* aead_read_ctx is the current read cipher state. */
SSL_AEAD_CTX *aead_read_ctx;
@@ -1750,7 +1757,6 @@
int ssl_verify_alarm_type(long type);
int ssl3_get_finished(SSL_HANDSHAKE *hs);
-int ssl3_send_change_cipher_spec(SSL *ssl);
int ssl3_send_alert(SSL *ssl, int level, int desc);
int ssl3_get_message(SSL *ssl, int msg_type,
enum ssl_hash_message_t hash_message);
@@ -1782,20 +1788,24 @@
int ssl3_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
int ssl3_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
-int ssl3_queue_message(SSL *ssl, uint8_t *msg, size_t len);
+int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len);
+int ssl3_add_change_cipher_spec(SSL *ssl);
+int ssl3_add_alert(SSL *ssl, uint8_t level, uint8_t desc);
int ssl3_write_message(SSL *ssl);
+int ssl3_flush_flight(SSL *ssl);
int dtls1_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
size_t *out_len);
-int dtls1_queue_message(SSL *ssl, uint8_t *msg, size_t len);
+int dtls1_add_message(SSL *ssl, uint8_t *msg, size_t len);
+int dtls1_add_change_cipher_spec(SSL *ssl);
+int dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc);
int dtls1_write_message(SSL *ssl);
-int dtls1_send_change_cipher_spec(SSL *ssl);
int dtls1_flush_flight(SSL *ssl);
-/* ssl_complete_message calls |finish_message| and |queue_message| on |cbb| to
- * queue the message for writing. */
-int ssl_complete_message(SSL *ssl, CBB *cbb);
+/* ssl_add_message_cbb finishes the handshake message in |cbb| and adds it to
+ * the pending flight. It returns one on success and zero on error. */
+int ssl_add_message_cbb(SSL *ssl, CBB *cbb);
/* ssl_hash_current_message incorporates the current handshake message into the
* handshake hash. It returns one on success and zero on allocation failure. */
@@ -1842,13 +1852,6 @@
void dtls1_release_current_message(SSL *ssl, int free_buffer);
int dtls1_dispatch_alert(SSL *ssl);
-/* ssl_is_wbio_buffered returns one if |ssl|'s write BIO is buffered and zero
- * otherwise. */
-int ssl_is_wbio_buffered(const SSL *ssl);
-
-int ssl_init_wbio_buffer(SSL *ssl);
-void ssl_free_wbio_buffer(SSL *ssl);
-
int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which);
int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len);
int tls1_generate_master_secret(SSL *ssl, uint8_t *out, const uint8_t *premaster,