1 /** 2 * TLS Protocol Version Management 3 * 4 * Copyright: 5 * (C) 2012 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.tls.version_; 12 13 import botan.constants; 14 static if (BOTAN_HAS_TLS): 15 16 import botan.utils.get_byte; 17 import botan.tls.exceptn; 18 import botan.tls.alert; 19 import botan.utils.parsing; 20 import botan.utils.types; 21 import std.conv : to; 22 23 /** 24 * TLS Protocol Version 25 */ 26 struct TLSProtocolVersion 27 { 28 public: 29 alias ushort VersionCode; 30 enum : VersionCode { 31 TLS_V10 = 0x0301, 32 TLS_V11 = 0x0302, 33 TLS_V12 = 0x0303, 34 35 DTLS_V10 = 0xFEFF, 36 DTLS_V12 = 0xFEFD 37 } 38 39 static TLSProtocolVersion latestTlsVersion() 40 { 41 return TLSProtocolVersion(TLS_V12); 42 } 43 44 static TLSProtocolVersion latestDtlsVersion() 45 { 46 return TLSProtocolVersion(DTLS_V12); 47 } 48 49 /** 50 * Params: 51 * named_version = a specific named version of the protocol 52 */ 53 this(VersionCode named_version) 54 { 55 m_version = cast(ushort) named_version; 56 } 57 58 /** 59 * Params: 60 * major = the major version 61 * minor = the minor version 62 */ 63 this(ubyte major, ubyte minor) 64 { 65 m_version = (cast(ushort)(major) << 8) | minor; 66 } 67 68 /** 69 * Returns: true if this is a valid protocol version 70 */ 71 bool valid() const { return (m_version != 0); } 72 73 /** 74 * Returns: true if this is a protocol version we know about 75 */ 76 bool knownVersion() const 77 { 78 return (m_version == TLSProtocolVersion.TLS_V10 || 79 m_version == TLSProtocolVersion.TLS_V11 || 80 m_version == TLSProtocolVersion.TLS_V12 || 81 m_version == TLSProtocolVersion.DTLS_V10 || 82 m_version == TLSProtocolVersion.DTLS_V12); 83 } 84 85 /** 86 * Returns: major version of the protocol version 87 */ 88 ubyte majorVersion() const { return get_byte(0, m_version); } 89 90 /** 91 * Returns: minor version of the protocol version 92 */ 93 ubyte minorVersion() const { return get_byte(1, m_version); } 94 95 /** 96 * Returns: human-readable description of this version 97 */ 98 string toString() const 99 { 100 const ubyte maj = majorVersion(); 101 const ubyte min = minorVersion(); 102 103 if (maj == 3 && min >= 1) // TLS v1.x 104 return "TLS v1." ~ to!string(min-1); 105 106 if (maj == 254) // DTLS 1.x 107 return "DTLS v1." ~ to!string(255 - min); 108 109 // Some very new or very old protocol (or bogus data) 110 return "Unknown " ~ to!string(maj) ~ "." ~ to!string(min); 111 } 112 113 /** 114 * Returns: true iff this is a DTLS version 115 */ 116 bool isDatagramProtocol() const 117 { 118 return majorVersion() == 254; 119 } 120 121 /** 122 * Returns: true if this version supports negotiable signature algorithms 123 */ 124 bool supportsNegotiableSignatureAlgorithms() const 125 { 126 return (m_version == TLSProtocolVersion.TLS_V12 || 127 m_version == TLSProtocolVersion.DTLS_V12); 128 } 129 130 /** 131 * Returns: true if this version uses explicit IVs for block ciphers 132 */ 133 bool supportsExplicitCbcIvs() const 134 { 135 return (m_version == TLSProtocolVersion.TLS_V11 || 136 m_version == TLSProtocolVersion.TLS_V12 || 137 m_version == TLSProtocolVersion.DTLS_V10 || 138 m_version == TLSProtocolVersion.DTLS_V12); 139 } 140 141 /** 142 * Returns: true if this version uses a ciphersuite specific PRF 143 */ 144 bool supportsCiphersuiteSpecificPrf() const 145 { 146 return (m_version == TLSProtocolVersion.TLS_V12 || 147 m_version == TLSProtocolVersion.DTLS_V12); 148 } 149 150 bool supportsAeadModes() const 151 { 152 return (m_version == TLSProtocolVersion.TLS_V12 || 153 m_version == TLSProtocolVersion.DTLS_V12); 154 } 155 156 /** 157 * Returns: if this version is equal to other 158 */ 159 bool opEquals(in TLSProtocolVersion other) const 160 { 161 return (m_version == other.m_version); 162 } 163 164 /** 165 * Returns: if this version is not equal to other 166 */ 167 int opCmp(in TLSProtocolVersion other) const 168 { 169 if (m_version == other.m_version) return 0; 170 else if (isGreaterThan(other)) return 1; 171 else return -1; 172 } 173 174 /** 175 * Returns: if this version is equal to other 176 */ 177 bool opEquals(in ushort other) const 178 { 179 return (m_version == other); 180 } 181 182 /** 183 * Returns: if this version is not equal to other 184 */ 185 int opCmp(in ushort other) const 186 { 187 if (m_version == other) return 0; 188 else if (isGreaterThan(TLSProtocolVersion(other))) return 1; 189 else return -1; 190 } 191 192 /** 193 * Returns: if this version is later than other 194 */ 195 bool isGreaterThan(in TLSProtocolVersion other) const 196 { 197 if (this.isDatagramProtocol() != other.isDatagramProtocol()) 198 throw new TLSException(TLSAlert.PROTOCOL_VERSION, 199 "Version comparing " ~ toString() ~ " with " ~ other.toString()); 200 201 if (this.isDatagramProtocol()) 202 return m_version < other.m_version; // goes backwards 203 204 return m_version > other.m_version; 205 } 206 private: 207 ushort m_version; 208 }