summary refs log tree commit diff
path: root/crypto/src/tls/ProtocolVersion.cs
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-07-12 15:15:36 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-07-12 15:15:36 +0700
commit68c795fe81277f73aeb90d8ad4c6f4305f32c906 (patch)
tree59643344aafef91bbd4c4a3a7973deba3d837a00 /crypto/src/tls/ProtocolVersion.cs
parentTLS test tweaks (diff)
downloadBouncyCastle.NET-ed25519-68c795fe81277f73aeb90d8ad4c6f4305f32c906.tar.xz
Port of new TLS API from bc-java
Diffstat (limited to 'crypto/src/tls/ProtocolVersion.cs')
-rw-r--r--crypto/src/tls/ProtocolVersion.cs406
1 files changed, 406 insertions, 0 deletions
diff --git a/crypto/src/tls/ProtocolVersion.cs b/crypto/src/tls/ProtocolVersion.cs
new file mode 100644
index 000000000..f37ce382d
--- /dev/null
+++ b/crypto/src/tls/ProtocolVersion.cs
@@ -0,0 +1,406 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Tls
+{
+    public sealed class ProtocolVersion
+    {
+        public static readonly ProtocolVersion SSLv3 = new ProtocolVersion(0x0300, "SSL 3.0");
+        public static readonly ProtocolVersion TLSv10 = new ProtocolVersion(0x0301, "TLS 1.0");
+        public static readonly ProtocolVersion TLSv11 = new ProtocolVersion(0x0302, "TLS 1.1");
+        public static readonly ProtocolVersion TLSv12 = new ProtocolVersion(0x0303, "TLS 1.2");
+        public static readonly ProtocolVersion TLSv13 = new ProtocolVersion(0x0304, "TLS 1.3");
+        public static readonly ProtocolVersion DTLSv10 = new ProtocolVersion(0xFEFF, "DTLS 1.0");
+        public static readonly ProtocolVersion DTLSv12 = new ProtocolVersion(0xFEFD, "DTLS 1.2");
+
+        internal static readonly ProtocolVersion CLIENT_EARLIEST_SUPPORTED_DTLS = DTLSv10;
+        internal static readonly ProtocolVersion CLIENT_EARLIEST_SUPPORTED_TLS = SSLv3;
+        internal static readonly ProtocolVersion CLIENT_LATEST_SUPPORTED_DTLS = DTLSv12;
+        internal static readonly ProtocolVersion CLIENT_LATEST_SUPPORTED_TLS = TLSv13;
+
+        internal static readonly ProtocolVersion SERVER_EARLIEST_SUPPORTED_DTLS = DTLSv10;
+        internal static readonly ProtocolVersion SERVER_EARLIEST_SUPPORTED_TLS = SSLv3;
+        internal static readonly ProtocolVersion SERVER_LATEST_SUPPORTED_DTLS = DTLSv12;
+        internal static readonly ProtocolVersion SERVER_LATEST_SUPPORTED_TLS = TLSv13;
+
+        public static bool Contains(ProtocolVersion[] versions, ProtocolVersion version)
+        {
+            if (versions != null && version != null)
+            {
+                for (int i = 0; i < versions.Length; ++i)
+                {
+                    if (version.Equals(versions[i]))
+                        return true;
+                }
+            }
+            return false;
+        }
+
+        public static ProtocolVersion GetEarliestDtls(ProtocolVersion[] versions)
+        {
+            ProtocolVersion earliest = null;
+            if (null != versions)
+            {
+                for (int i = 0; i < versions.Length; ++i)
+                {
+                    ProtocolVersion next = versions[i];
+                    if (null != next && next.IsDtls)
+                    {
+                        if (null == earliest || next.MinorVersion > earliest.MinorVersion)
+                        {
+                            earliest = next;
+                        }
+                    }
+                }
+            }
+            return earliest;
+        }
+
+        public static ProtocolVersion GetEarliestTls(ProtocolVersion[] versions)
+        {
+            ProtocolVersion earliest = null;
+            if (null != versions)
+            {
+                for (int i = 0; i < versions.Length; ++i)
+                {
+                    ProtocolVersion next = versions[i];
+                    if (null != next && next.IsTls)
+                    {
+                        if (null == earliest || next.MinorVersion < earliest.MinorVersion)
+                        {
+                            earliest = next;
+                        }
+                    }
+                }
+            }
+            return earliest;
+        }
+
+        public static ProtocolVersion GetLatestDtls(ProtocolVersion[] versions)
+        {
+            ProtocolVersion latest = null;
+            if (null != versions)
+            {
+                for (int i = 0; i < versions.Length; ++i)
+                {
+                    ProtocolVersion next = versions[i];
+                    if (null != next && next.IsDtls)
+                    {
+                        if (null == latest || next.MinorVersion < latest.MinorVersion)
+                        {
+                            latest = next;
+                        }
+                    }
+                }
+            }
+            return latest;
+        }
+
+        public static ProtocolVersion GetLatestTls(ProtocolVersion[] versions)
+        {
+            ProtocolVersion latest = null;
+            if (null != versions)
+            {
+                for (int i = 0; i < versions.Length; ++i)
+                {
+                    ProtocolVersion next = versions[i];
+                    if (null != next && next.IsTls)
+                    {
+                        if (null == latest || next.MinorVersion > latest.MinorVersion)
+                        {
+                            latest = next;
+                        }
+                    }
+                }
+            }
+            return latest;
+        }
+
+        internal static bool IsSupportedDtlsVersionClient(ProtocolVersion version)
+        {
+            return null != version
+                && version.IsEqualOrLaterVersionOf(CLIENT_EARLIEST_SUPPORTED_DTLS)
+                && version.IsEqualOrEarlierVersionOf(CLIENT_LATEST_SUPPORTED_DTLS);
+        }
+
+        internal static bool IsSupportedDtlsVersionServer(ProtocolVersion version)
+        {
+            return null != version
+                && version.IsEqualOrLaterVersionOf(SERVER_EARLIEST_SUPPORTED_DTLS)
+                && version.IsEqualOrEarlierVersionOf(SERVER_LATEST_SUPPORTED_DTLS);
+        }
+
+        internal static bool IsSupportedTlsVersionClient(ProtocolVersion version)
+        {
+            if (null == version)
+                return false;
+
+            int fullVersion = version.FullVersion;
+
+            return fullVersion >= CLIENT_EARLIEST_SUPPORTED_TLS.FullVersion
+                && fullVersion <= CLIENT_LATEST_SUPPORTED_TLS.FullVersion;
+        }
+
+        internal static bool IsSupportedTlsVersionServer(ProtocolVersion version)
+        {
+            if (null == version)
+                return false;
+
+            int fullVersion = version.FullVersion;
+
+            return fullVersion >= SERVER_EARLIEST_SUPPORTED_TLS.FullVersion
+                && fullVersion <= SERVER_LATEST_SUPPORTED_TLS.FullVersion;
+        }
+
+        private readonly int version;
+        private readonly string name;
+
+        private ProtocolVersion(int v, string name)
+        {
+            this.version = v & 0xFFFF;
+            this.name = name;
+        }
+
+        public ProtocolVersion[] DownTo(ProtocolVersion min)
+        {
+            if (!IsEqualOrLaterVersionOf(min))
+                throw new ArgumentException("must be an equal or earlier version of this one", "min");
+
+            IList result = Platform.CreateArrayList();
+            result.Add(this);
+
+            ProtocolVersion current = this;
+            while (!current.Equals(min))
+            {
+                current = current.GetPreviousVersion();
+                result.Add(current);
+            }
+
+            ProtocolVersion[] versions = new ProtocolVersion[result.Count];
+            for (int i = 0; i < result.Count; ++i)
+            {
+                versions[i] = (ProtocolVersion)result[i];
+            }
+            return versions;
+        }
+
+        public int FullVersion
+        {
+            get { return version; }
+        }
+
+        public int MajorVersion
+        {
+            get { return version >> 8; }
+        }
+
+        public int MinorVersion
+        {
+            get { return version & 0xFF; }
+        }
+
+        public string Name
+        {
+            get { return name; }
+        }
+
+        public bool IsDtls
+        {
+            get { return MajorVersion == 0xFE; }
+        }
+
+        public bool IsSsl
+        {
+            get { return this == SSLv3; }
+        }
+
+        public bool IsTls
+        {
+            get { return MajorVersion == 0x03; }
+        }
+
+        public ProtocolVersion GetEquivalentTlsVersion()
+        {
+            switch (MajorVersion)
+            {
+                case 0x03:
+                    return this;
+                case 0xFE:
+                    switch (MinorVersion)
+                    {
+                        case 0xFF: return TLSv11;
+                        case 0xFD: return TLSv12;
+                        default: return null;
+                    }
+                default:
+                    return null;
+            }
+        }
+
+        public ProtocolVersion GetNextVersion()
+        {
+            int major = MajorVersion, minor = MinorVersion;
+            switch (major)
+            {
+            case 0x03:
+                switch (minor)
+                {
+                    case 0xFF: return null;
+                    default: return Get(major, minor + 1);
+                }
+            case 0xFE:
+                switch (minor)
+                {
+                    case 0x00: return null;
+                    case 0xFF: return DTLSv12;
+                    default: return Get(major, minor - 1);
+                }
+            default:
+                return null;
+            }
+        }
+
+        public ProtocolVersion GetPreviousVersion()
+        {
+            int major = MajorVersion, minor = MinorVersion;
+            switch (major)
+            {
+                case 0x03:
+                    switch (minor)
+                    {
+                        case 0x00: return null;
+                        default: return Get(major, minor - 1);
+                    }
+                case 0xFE:
+                    switch (minor)
+                    {
+                        case 0xFF: return null;
+                        case 0xFD: return DTLSv10;
+                        default: return Get(major, minor + 1);
+                    }
+                default:
+                    return null;
+            }
+        }
+
+        public bool IsEarlierVersionOf(ProtocolVersion version)
+        {
+            if (null == version || MajorVersion != version.MajorVersion)
+                return false;
+
+            int diffMinorVersion = MinorVersion - version.MinorVersion;
+            return IsDtls ? diffMinorVersion > 0 : diffMinorVersion < 0;
+        }
+
+        public bool IsEqualOrEarlierVersionOf(ProtocolVersion version)
+        {
+            if (null == version || MajorVersion != version.MajorVersion)
+                return false;
+
+            int diffMinorVersion = MinorVersion - version.MinorVersion;
+            return IsDtls ? diffMinorVersion >= 0 : diffMinorVersion <= 0;
+        }
+
+        public bool IsEqualOrLaterVersionOf(ProtocolVersion version)
+        {
+            if (null == version || MajorVersion != version.MajorVersion)
+                return false;
+
+            int diffMinorVersion = MinorVersion - version.MinorVersion;
+            return IsDtls ? diffMinorVersion <= 0 : diffMinorVersion >= 0;
+        }
+
+        public bool IsLaterVersionOf(ProtocolVersion version)
+        {
+            if (null == version || MajorVersion != version.MajorVersion)
+                return false;
+
+            int diffMinorVersion = MinorVersion - version.MinorVersion;
+            return IsDtls ? diffMinorVersion < 0 : diffMinorVersion > 0;
+        }
+
+        public override bool Equals(object other)
+        {
+            return this == other || (other is ProtocolVersion && Equals((ProtocolVersion)other));
+        }
+
+        public bool Equals(ProtocolVersion other)
+        {
+            return other != null && this.version == other.version;
+        }
+
+        public override int GetHashCode()
+        {
+            return version;
+        }
+
+        public static ProtocolVersion Get(int major, int minor)
+        {
+            switch (major)
+            {
+            case 0x03:
+            {
+                switch (minor)
+                {
+                case 0x00:
+                    return SSLv3;
+                case 0x01:
+                    return TLSv10;
+                case 0x02:
+                    return TLSv11;
+                case 0x03:
+                    return TLSv12;
+                case 0x04:
+                    return TLSv13;
+                }
+                return GetUnknownVersion(major, minor, "TLS");
+            }
+            case 0xFE:
+            {
+                switch (minor)
+                {
+                case 0xFF:
+                    return DTLSv10;
+                case 0xFE:
+                    throw new ArgumentException("{0xFE, 0xFE} is a reserved protocol version");
+                case 0xFD:
+                    return DTLSv12;
+                }
+                return GetUnknownVersion(major, minor, "DTLS");
+            }
+            default:
+            {
+                return GetUnknownVersion(major, minor, "UNKNOWN");
+            }
+            }
+        }
+
+        public ProtocolVersion[] Only()
+        {
+            return new ProtocolVersion[]{ this };
+        }
+
+        public override string ToString()
+        {
+            return name;
+        }
+
+        private static void CheckUint8(int versionOctet)
+        {
+            if (!TlsUtilities.IsValidUint8(versionOctet))
+                throw new ArgumentException("not a valid octet", "versionOctet");
+        }
+
+        private static ProtocolVersion GetUnknownVersion(int major, int minor, string prefix)
+        {
+            CheckUint8(major);
+            CheckUint8(minor);
+
+            int v = (major << 8) | minor;
+            string hex = Platform.ToUpperInvariant(Convert.ToString(0x10000 | v, 16).Substring(1));
+            return new ProtocolVersion(v, prefix + " 0x" + hex);
+        }
+    }
+}