Convert more of the SSL write path to size_t and Spans.

We still have our <= 0 return values because anything with BIOs tries to
preserve BIO_write's error returns. (Maybe we can stop doing this?
BIO_read's error return is a little subtle with EOF vs error, but
BIO_write's is uninteresting.) But the rest of the logic is size_t-clean
and hopefully a little clearer. We still have to support SSL_write's
rather goofy calling convention, however.

I haven't pushed Spans down into the low-level record construction logic
yet. We should probably do that, but there are enough offsets tossed
around there that they warrant their own CL.

Bug: 507
Change-Id: Ia0c702d1a2d3713e71b0bbfa8d65649d3b20da9b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47544
Commit-Queue: Bob Beck <bbe@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/ssl/d1_pkt.cc b/ssl/d1_pkt.cc
index b9b0ef9..b866156 100644
--- a/ssl/d1_pkt.cc
+++ b/ssl/d1_pkt.cc
@@ -186,8 +186,8 @@
   return ssl_open_record_success;
 }
 
-int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *in,
-                         int len) {
+int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake,
+                         size_t *out_bytes_written, Span<const uint8_t> in) {
   assert(!SSL_in_init(ssl));
   *out_needs_handshake = false;
 
@@ -196,47 +196,46 @@
     return -1;
   }
 
-  if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
+  // DTLS does not split the input across records.
+  if (in.size() > SSL3_RT_MAX_PLAIN_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DTLS_MESSAGE_TOO_BIG);
     return -1;
   }
 
-  if (len < 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
-    return -1;
+  if (in.empty()) {
+    *out_bytes_written = 0;
+    return 1;
   }
 
-  if (len == 0) {
-    return 0;
-  }
-
-  int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, in, (size_t)len,
+  int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, in,
                                dtls1_use_current_epoch);
   if (ret <= 0) {
     return ret;
   }
-  return len;
+  *out_bytes_written = in.size();
+  return 1;
 }
 
-int dtls1_write_record(SSL *ssl, int type, const uint8_t *in, size_t len,
+int dtls1_write_record(SSL *ssl, int type, Span<const uint8_t> in,
                        enum dtls1_use_epoch_t use_epoch) {
   SSLBuffer *buf = &ssl->s3->write_buffer;
-  assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
+  assert(in.size() <= SSL3_RT_MAX_PLAIN_LENGTH);
   // There should never be a pending write buffer in DTLS. One can't write half
   // a datagram, so the write buffer is always dropped in
   // |ssl_write_buffer_flush|.
   assert(buf->empty());
 
-  if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
+  if (in.size() > SSL3_RT_MAX_PLAIN_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return -1;
   }
 
   size_t ciphertext_len;
   if (!buf->EnsureCap(ssl_seal_align_prefix_len(ssl),
-                      len + SSL_max_seal_overhead(ssl)) ||
+                      in.size() + SSL_max_seal_overhead(ssl)) ||
       !dtls_seal_record(ssl, buf->remaining().data(), &ciphertext_len,
-                        buf->remaining().size(), type, in, len, use_epoch)) {
+                        buf->remaining().size(), type, in.data(), in.size(),
+                        use_epoch)) {
     buf->Clear();
     return -1;
   }
@@ -250,7 +249,7 @@
 }
 
 int dtls1_dispatch_alert(SSL *ssl) {
-  int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2,
+  int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, ssl->s3->send_alert,
                                dtls1_use_current_epoch);
   if (ret <= 0) {
     return ret;