Add bssl::SealRecord and bssl::OpenRecord.

This is a C++ interface for encrypting and decrypting TLS application
data records in-place, wrapping the existing C API in tls_record.cc.

Also add bssl::Span, a non-owning reference to a contiguous array of
elements which can be used as a common interface over contiguous
container types (like std::vector), pointer-length-pairs, arrays, etc.

Change-Id: Iaa2ca4957cde511cb734b997db38f54e103b0d92
Reviewed-on: https://boringssl-review.googlesource.com/18104
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 04ec4b8..993046c 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -149,6 +149,7 @@
 #include <openssl/hmac.h>
 #include <openssl/lhash.h>
 #include <openssl/pem.h>
+#include <openssl/span.h>
 #include <openssl/ssl3.h>
 #include <openssl/thread.h>
 #include <openssl/tls1.h>
@@ -4580,6 +4581,8 @@
 #if defined(__cplusplus)
 } /* extern C */
 
+#if !defined(BORINGSSL_NO_CXX)
+
 extern "C++" {
 
 namespace bssl {
@@ -4588,10 +4591,62 @@
 BORINGSSL_MAKE_DELETER(SSL_CTX, SSL_CTX_free)
 BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free)
 
+enum class OpenRecordResult {
+  kOK,
+  kDiscard,
+  kIncompleteRecord,
+  kAlertCloseNotify,
+  kAlertFatal,
+  kError,
+};
+
+/*  *** EXPERIMENTAL -- DO NOT USE ***
+ *
+ * OpenRecord decrypts the first complete SSL record from |in| in-place, sets
+ * |out| to the decrypted application data, and |out_record_len| to the length
+ * of the encrypted record. Returns:
+ * - kOK if an application-data record was successfully decrypted and verified.
+ * - kDiscard if a record was sucessfully processed, but should be discarded.
+ * - kIncompleteRecord if |in| did not contain a complete record.
+ * - kAlertCloseNotify if a record was successfully processed but is a
+ *   close_notify alert.
+ * - kAlertFatal if a record was successfully processed but is a fatal alert.
+ * - kError if an error occurred or the record is invalid. |*out_alert| will be
+ *   set to an alert to emit. */
+OPENSSL_EXPORT OpenRecordResult OpenRecord(SSL *ssl, Span<uint8_t> *out,
+                                           size_t *out_record_len,
+                                           uint8_t *out_alert,
+                                           Span<uint8_t> in);
+
+OPENSSL_EXPORT size_t SealRecordPrefixLen(SSL *ssl, size_t plaintext_len);
+OPENSSL_EXPORT size_t SealRecordMaxSuffixLen(SSL *ssl);
+
+/*  *** EXPERIMENTAL -- DO NOT USE ***
+ *
+ * SealRecord encrypts the cleartext of |in| and scatters the resulting TLS
+ * application data record between |out_prefix|, |out|, and |out_suffix|. It
+ * returns true on success or false if an error occurred.
+ *
+ * The length of |out_prefix| must equal |SealRecordPrefixLen|. The length of
+ * |out| must equal the length of |in|. The length of |out_suffix| must equal
+ * |MaxSealRecordSuffixLen|. |*out_suffix_len| is set to the actual number of
+ * bytes written to |out_suffix|.
+ *
+ * If enabled, |SealRecord| may perform TLS 1.0 CBC 1/n-1 record splitting.
+ * |SealRecordPrefixLen| accounts for the required overhead if that is the case.
+ *
+ * |out| may equal |in| to encrypt in-place but may not otherwise alias.
+ * |out_prefix| and |out_suffix| may not alias anything. */
+OPENSSL_EXPORT bool SealRecord(SSL *ssl, Span<uint8_t> out_prefix,
+                               Span<uint8_t> out, Span<uint8_t> out_suffix,
+                               size_t *out_suffix_len, Span<const uint8_t> in);
+
 }  // namespace bssl
 
 }  /* extern C++ */
 
+#endif  // !defined(BORINGSSL_NO_CXX)
+
 #endif
 
 #define SSL_R_APP_DATA_IN_HANDSHAKE 100