package org.bouncycastle.tls; import java.io.IOException; import org.bouncycastle.util.Strings; public final class ProtocolVersion { public static final ProtocolVersion SSLv3 = new ProtocolVersion(0x0300, "SSL 3.0"); public static final ProtocolVersion TLSv10 = new ProtocolVersion(0x0301, "TLS 1.0"); public static final ProtocolVersion TLSv11 = new ProtocolVersion(0x0302, "TLS 1.1"); public static final ProtocolVersion TLSv12 = new ProtocolVersion(0x0303, "TLS 1.2"); public static final ProtocolVersion DTLSv10 = new ProtocolVersion(0xFEFF, "DTLS 1.0"); public static final ProtocolVersion DTLSv12 = new ProtocolVersion(0xFEFD, "DTLS 1.2"); private int version; private String name; private ProtocolVersion(int v, String name) { this.version = v & 0xFFFF; this.name = name; } public int getFullVersion() { return version; } public int getMajorVersion() { return version >> 8; } public int getMinorVersion() { return version & 0xFF; } public boolean isDTLS() { return getMajorVersion() == 0xFE; } public boolean isSSL() { return getFullVersion() == SSLv3.getFullVersion(); } public boolean isTLS() { return getMajorVersion() == 0x03; } public ProtocolVersion getEquivalentTLSVersion() { if (isTLS()) { return this; } switch (getMinorVersion()) { case 0xFF: return TLSv11; case 0xFD: return TLSv12; default: return null; } } public ProtocolVersion getPreviousVersion() throws IOException { if (isDTLS()) { switch(getMinorVersion()) { case 0xFF: return null; case 0xFD: return DTLSv10; default : return get(getMajorVersion(), getMinorVersion() + 1); } } else { switch (getMinorVersion()) { case 0x00: return null; default : return get(getMajorVersion(), getMinorVersion() - 1); } } } public boolean isEqualOrEarlierVersionOf(ProtocolVersion version) { if (getMajorVersion() != version.getMajorVersion()) { return false; } int diffMinorVersion = version.getMinorVersion() - getMinorVersion(); return isDTLS() ? diffMinorVersion <= 0 : diffMinorVersion >= 0; } public boolean isLaterVersionOf(ProtocolVersion version) { if (getMajorVersion() != version.getMajorVersion()) { return false; } int diffMinorVersion = version.getMinorVersion() - getMinorVersion(); return isDTLS() ? diffMinorVersion > 0 : diffMinorVersion < 0; } public boolean equals(Object other) { return this == other || (other instanceof ProtocolVersion && equals((ProtocolVersion)other)); } public boolean equals(ProtocolVersion other) { return other != null && this.version == other.version; } public int hashCode() { return version; } public static ProtocolVersion get(int major, int minor) throws IOException { switch (major) { case 0x03: { switch (minor) { case 0x00: return SSLv3; case 0x01: return TLSv10; case 0x02: return TLSv11; case 0x03: return TLSv12; } return getUnknownVersion(major, minor, "TLS"); } case 0xFE: { switch (minor) { case 0xFF: return DTLSv10; case 0xFE: throw new TlsFatalAlert(AlertDescription.illegal_parameter); case 0xFD: return DTLSv12; } return getUnknownVersion(major, minor, "DTLS"); } default: { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } } public String toString() { return name; } private static ProtocolVersion getUnknownVersion(int major, int minor, String prefix) throws IOException { TlsUtils.checkUint8(major); TlsUtils.checkUint8(minor); int v = (major << 8) | minor; String hex = Strings.toUpperCase(Integer.toHexString(0x10000 | v).substring(1)); return new ProtocolVersion(v, prefix + " 0x" + hex); } }