diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-07-12 15:15:36 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-07-12 15:15:36 +0700 |
commit | 68c795fe81277f73aeb90d8ad4c6f4305f32c906 (patch) | |
tree | 59643344aafef91bbd4c4a3a7973deba3d837a00 /crypto/src/tls/ProtocolVersion.cs | |
parent | TLS test tweaks (diff) | |
download | BouncyCastle.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.cs | 406 |
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); + } + } +} |