Allow dtls_seal_record to work in-place.

This will let us avoid a scratch buffer when assembling DTLS handshake
packets in the write_message-less flow.

BUG=72

Change-Id: I15e78efe3a9e3933c307e599f0043427330f4a9e
Reviewed-on: https://boringssl-review.googlesource.com/13262
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/dtls_record.c b/ssl/dtls_record.c
index e507f5c..35c08b0 100644
--- a/ssl/dtls_record.c
+++ b/ssl/dtls_record.c
@@ -249,10 +249,24 @@
   return ssl_open_record_success;
 }
 
+size_t dtls_seal_prefix_len(const SSL *ssl, enum dtls1_use_epoch_t use_epoch) {
+  const SSL_AEAD_CTX *aead = ssl->s3->aead_write_ctx;
+  if (use_epoch == dtls1_use_previous_epoch) {
+    /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1
+     * (negotiated cipher) exist. */
+    assert(ssl->d1->w_epoch == 1);
+    aead = NULL;
+  }
+
+  return DTLS1_RT_HEADER_LENGTH + SSL_AEAD_CTX_explicit_nonce_len(aead);
+}
+
 int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
                      uint8_t type, const uint8_t *in, size_t in_len,
                      enum dtls1_use_epoch_t use_epoch) {
-  if (buffers_alias(in, in_len, out, max_out)) {
+  const size_t prefix = dtls_seal_prefix_len(ssl, use_epoch);
+  if (buffers_alias(in, in_len, out, max_out) &&
+      (max_out < prefix || out + prefix != in)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
     return 0;
   }
diff --git a/ssl/internal.h b/ssl/internal.h
index 068f95f..9557828 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -307,11 +307,11 @@
 
 /* SSL_AEAD_CTX_explicit_nonce_len returns the length of the explicit nonce for
  * |ctx|, if any. |ctx| may be NULL to denote the null cipher. */
-size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *ctx);
+size_t SSL_AEAD_CTX_explicit_nonce_len(const SSL_AEAD_CTX *ctx);
 
 /* SSL_AEAD_CTX_max_overhead returns the maximum overhead of calling
  * |SSL_AEAD_CTX_seal|. |ctx| may be NULL to denote the null cipher. */
-size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *ctx);
+size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *ctx);
 
 /* SSL_AEAD_CTX_open authenticates and decrypts |in_len| bytes from |in|
  * in-place. On success, it sets |*out| to the plaintext in |in| and returns
@@ -407,12 +407,11 @@
  * use this to align buffers.
  *
  * Note when TLS 1.0 CBC record-splitting is enabled, this includes the one byte
- * record and is the offset into second record's ciphertext. Thus this value may
- * differ from |ssl_record_prefix_len| and sealing a small record may result in
- * a smaller output than this value.
+ * record and is the offset into second record's ciphertext. Thus sealing a
+ * small record may result in a smaller output than this value.
  *
- * TODO(davidben): Expose this as part of public API once the high-level
- * buffer-free APIs are available. */
+ * TODO(davidben): Is this alignment valuable? Record-splitting makes this a
+ * mess. */
 size_t ssl_seal_align_prefix_len(const SSL *ssl);
 
 /* tls_seal_record seals a new record of type |type| and body |in| and writes it
@@ -434,8 +433,14 @@
   dtls1_use_current_epoch,
 };
 
+/* dtls_seal_prefix_len returns the number of bytes of prefix to reserve in
+ * front of the plaintext when sealing a record in-place. */
+size_t dtls_seal_prefix_len(const SSL *ssl, enum dtls1_use_epoch_t use_epoch);
+
 /* dtls_seal_record implements |tls_seal_record| for DTLS. |use_epoch| selects
- * which epoch's cipher state to use. */
+ * which epoch's cipher state to use. Unlike |tls_seal_record|, |in| and |out|
+ * may alias but, if they do, |in| must be exactly |dtls_seal_prefix_len| bytes
+ * ahead of |out|. */
 int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
                      uint8_t type, const uint8_t *in, size_t in_len,
                      enum dtls1_use_epoch_t use_epoch);
diff --git a/ssl/ssl_aead_ctx.c b/ssl/ssl_aead_ctx.c
index bba55ef..e18ba69 100644
--- a/ssl/ssl_aead_ctx.c
+++ b/ssl/ssl_aead_ctx.c
@@ -126,7 +126,7 @@
   OPENSSL_free(aead);
 }
 
-size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *aead) {
+size_t SSL_AEAD_CTX_explicit_nonce_len(const SSL_AEAD_CTX *aead) {
 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
   aead = NULL;
 #endif
@@ -137,7 +137,7 @@
   return 0;
 }
 
-size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *aead) {
+size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *aead) {
 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
   aead = NULL;
 #endif