summary refs log tree commit diff
path: root/crypto/src/tls/RecordStream.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/tls/RecordStream.cs')
-rw-r--r--crypto/src/tls/RecordStream.cs51
1 files changed, 51 insertions, 0 deletions
diff --git a/crypto/src/tls/RecordStream.cs b/crypto/src/tls/RecordStream.cs
index a97d34698..a5926d05b 100644
--- a/crypto/src/tls/RecordStream.cs
+++ b/crypto/src/tls/RecordStream.cs
@@ -258,6 +258,9 @@ namespace Org.BouncyCastle.Tls
         /// <exception cref="IOException"/>
         internal void WriteRecord(short contentType, byte[] plaintext, int plaintextOffset, int plaintextLength)
         {
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            WriteRecord(contentType, plaintext.AsSpan(plaintextOffset, plaintextLength));
+#else
             // Never send anything until a valid ClientHello has been received
             if (m_writeVersion == null)
                 return;
@@ -298,8 +301,56 @@ namespace Org.BouncyCastle.Tls
             //}
 
             m_output.Flush();
+#endif
         }
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        /// <exception cref="IOException"/>
+        internal void WriteRecord(short contentType, ReadOnlySpan<byte> plaintext)
+        {
+            // Never send anything until a valid ClientHello has been received
+            if (m_writeVersion == null)
+                return;
+
+            /*
+             * RFC 5246 6.2.1 The length should not exceed 2^14.
+             */
+            CheckLength(plaintext.Length, m_plaintextLimit, AlertDescription.internal_error);
+
+            /*
+             * RFC 5246 6.2.1 Implementations MUST NOT send zero-length fragments of Handshake, Alert,
+             * or ChangeCipherSpec content types.
+             */
+            if (plaintext.Length < 1 && contentType != ContentType.application_data)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            long seqNo = m_writeSeqNo.NextValue(AlertDescription.internal_error);
+            ProtocolVersion recordVersion = m_writeVersion;
+
+            TlsEncodeResult encoded = m_writeCipher.EncodePlaintext(seqNo, contentType, recordVersion,
+                RecordFormat.FragmentOffset, plaintext);
+
+            int ciphertextLength = encoded.len - RecordFormat.FragmentOffset;
+            TlsUtilities.CheckUint16(ciphertextLength);
+
+            TlsUtilities.WriteUint8(encoded.recordType, encoded.buf, encoded.off + RecordFormat.TypeOffset);
+            TlsUtilities.WriteVersion(recordVersion, encoded.buf, encoded.off + RecordFormat.VersionOffset);
+            TlsUtilities.WriteUint16(ciphertextLength, encoded.buf, encoded.off + RecordFormat.LengthOffset);
+
+            // TODO[tls-port] Can we support interrupted IO on .NET?
+            //try
+            //{
+                m_output.Write(encoded.buf, encoded.off, encoded.len);
+            //}
+            //catch (InterruptedIOException e)
+            //{
+            //    throw new TlsFatalAlert(AlertDescription.internal_error, e);
+            //}
+
+            m_output.Flush();
+        }
+#endif
+
         /// <exception cref="IOException"/>
         internal void Close()
         {