diff options
Diffstat (limited to 'crypto/src/tls/DtlsTransport.cs')
-rw-r--r-- | crypto/src/tls/DtlsTransport.cs | 111 |
1 files changed, 105 insertions, 6 deletions
diff --git a/crypto/src/tls/DtlsTransport.cs b/crypto/src/tls/DtlsTransport.cs index a41cb7866..033e0af0b 100644 --- a/crypto/src/tls/DtlsTransport.cs +++ b/crypto/src/tls/DtlsTransport.cs @@ -1,8 +1,6 @@ using System; using System.IO; -#if !PORTABLE || DOTNET using System.Net.Sockets; -#endif namespace Org.BouncyCastle.Tls { @@ -10,10 +8,12 @@ namespace Org.BouncyCastle.Tls : DatagramTransport { private readonly DtlsRecordLayer m_recordLayer; + private readonly bool m_ignoreCorruptRecords; - internal DtlsTransport(DtlsRecordLayer recordLayer) + internal DtlsTransport(DtlsRecordLayer recordLayer, bool ignoreCorruptRecords) { - this.m_recordLayer = recordLayer; + m_recordLayer = recordLayer; + m_ignoreCorruptRecords = ignoreCorruptRecords; } /// <exception cref="IOException"/> @@ -37,6 +37,10 @@ namespace Org.BouncyCastle.Tls throw new ArgumentException("invalid offset: " + off, "off"); if (len < 0 || len > buf.Length - off) throw new ArgumentException("invalid length: " + len, "len"); + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return Receive(buf.AsSpan(off, len), waitMillis); +#else if (waitMillis < 0) throw new ArgumentException("cannot be negative", "waitMillis"); @@ -46,6 +50,9 @@ namespace Org.BouncyCastle.Tls } catch (TlsFatalAlert fatalAlert) { + if (m_ignoreCorruptRecords && AlertDescription.bad_record_mac == fatalAlert.AlertDescription) + return -1; + m_recordLayer.Fail(fatalAlert.AlertDescription); throw fatalAlert; } @@ -53,7 +60,6 @@ namespace Org.BouncyCastle.Tls { throw e; } -#if !PORTABLE || DOTNET catch (SocketException e) { if (TlsUtilities.IsTimeout(e)) @@ -62,7 +68,55 @@ namespace Org.BouncyCastle.Tls m_recordLayer.Fail(AlertDescription.internal_error); throw new TlsFatalAlert(AlertDescription.internal_error, e); } + // TODO[tls-port] Can we support interrupted IO on .NET? + //catch (InterruptedIOException e) + //{ + // throw e; + //} + catch (IOException e) + { + m_recordLayer.Fail(AlertDescription.internal_error); + throw e; + } + catch (Exception e) + { + m_recordLayer.Fail(AlertDescription.internal_error); + throw new TlsFatalAlert(AlertDescription.internal_error, e); + } #endif + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + /// <exception cref="IOException"/> + public virtual int Receive(Span<byte> buffer, int waitMillis) + { + if (waitMillis < 0) + throw new ArgumentException("cannot be negative", nameof(waitMillis)); + + try + { + return m_recordLayer.Receive(buffer, waitMillis); + } + catch (TlsFatalAlert fatalAlert) + { + if (m_ignoreCorruptRecords && AlertDescription.bad_record_mac == fatalAlert.AlertDescription) + return -1; + + m_recordLayer.Fail(fatalAlert.AlertDescription); + throw fatalAlert; + } + catch (TlsTimeoutException e) + { + throw e; + } + catch (SocketException e) + { + if (TlsUtilities.IsTimeout(e)) + throw e; + + m_recordLayer.Fail(AlertDescription.internal_error); + throw new TlsFatalAlert(AlertDescription.internal_error, e); + } // TODO[tls-port] Can we support interrupted IO on .NET? //catch (InterruptedIOException e) //{ @@ -79,6 +133,7 @@ namespace Org.BouncyCastle.Tls throw new TlsFatalAlert(AlertDescription.internal_error, e); } } +#endif /// <exception cref="IOException"/> public virtual void Send(byte[] buf, int off, int len) @@ -90,6 +145,9 @@ namespace Org.BouncyCastle.Tls if (len < 0 || len > buf.Length - off) throw new ArgumentException("invalid length: " + len, "len"); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Send(buf.AsSpan(off, len)); +#else try { m_recordLayer.Send(buf, off, len); @@ -103,7 +161,6 @@ namespace Org.BouncyCastle.Tls { throw e; } -#if !PORTABLE || DOTNET catch (SocketException e) { if (TlsUtilities.IsTimeout(e)) @@ -112,7 +169,48 @@ namespace Org.BouncyCastle.Tls m_recordLayer.Fail(AlertDescription.internal_error); throw new TlsFatalAlert(AlertDescription.internal_error, e); } + // TODO[tls-port] Can we support interrupted IO on .NET? + //catch (InterruptedIOException e) + //{ + // throw e; + //} + catch (IOException e) + { + m_recordLayer.Fail(AlertDescription.internal_error); + throw e; + } + catch (Exception e) + { + m_recordLayer.Fail(AlertDescription.internal_error); + throw new TlsFatalAlert(AlertDescription.internal_error, e); + } #endif + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void Send(ReadOnlySpan<byte> buffer) + { + try + { + m_recordLayer.Send(buffer); + } + catch (TlsFatalAlert fatalAlert) + { + m_recordLayer.Fail(fatalAlert.AlertDescription); + throw fatalAlert; + } + catch (TlsTimeoutException e) + { + throw e; + } + catch (SocketException e) + { + if (TlsUtilities.IsTimeout(e)) + throw e; + + m_recordLayer.Fail(AlertDescription.internal_error); + throw new TlsFatalAlert(AlertDescription.internal_error, e); + } // TODO[tls-port] Can we support interrupted IO on .NET? //catch (InterruptedIOException e) //{ @@ -129,6 +227,7 @@ namespace Org.BouncyCastle.Tls throw new TlsFatalAlert(AlertDescription.internal_error, e); } } +#endif /// <exception cref="IOException"/> public virtual void Close() |