github.com/mholt/caddy-l4@v0.0.0-20241104153248-ec8fae209322/modules/l4tls/parsehello.go (about) 1 // Copyright 2020 Matthew Holt 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package l4tls 16 17 import ( 18 "crypto/tls" 19 "strings" 20 21 "golang.org/x/crypto/cryptobyte" 22 ) 23 24 // Most of this file is borrowed from the Go standard library, ca. May 2020. 25 // It was written by the Go Authors and has this copyright: 26 // 27 // Copyright 2009 The Go Authors. All rights reserved. 28 // Use of this source code is governed by a BSD-style 29 // license that can be found in the LICENSE file. 30 // 31 // This code has been modified since then. 32 33 func parseRawClientHello(data []byte) (info ClientHelloInfo) { 34 defer func() { 35 if len(info.SupportedVersions) == 0 { 36 info.SupportedVersions = supportedVersionsFromMax(info.Version) 37 } 38 }() 39 40 s := cryptobyte.String(data) 41 42 if !s.Skip(4) || // message type and uint24 length field 43 !s.ReadUint16(&info.Version) || !s.ReadBytes(&info.Random, 32) || 44 !readUint8LengthPrefixed(&s, &info.SessionID) { 45 return 46 } 47 48 var cipherSuites cryptobyte.String 49 if !s.ReadUint16LengthPrefixed(&cipherSuites) { 50 return 51 } 52 for !cipherSuites.Empty() { 53 var suite uint16 54 if !cipherSuites.ReadUint16(&suite) { 55 return 56 } 57 if suite == scsvRenegotiation { 58 info.SecureRenegotiationSupported = true 59 } 60 info.CipherSuites = append(info.CipherSuites, suite) 61 } 62 63 if !readUint8LengthPrefixed(&s, &info.CompressionMethods) { 64 return 65 } 66 67 if s.Empty() { 68 // ClientHello is optionally followed by extension data 69 return 70 } 71 72 var extensions cryptobyte.String 73 if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { 74 return 75 } 76 77 for !extensions.Empty() { 78 var extension uint16 79 var extData cryptobyte.String 80 if !extensions.ReadUint16(&extension) || 81 !extensions.ReadUint16LengthPrefixed(&extData) { 82 return 83 } 84 85 // record that client advertised support for this extension 86 info.Extensions = append(info.Extensions, extension) 87 88 switch extension { 89 case extensionServerName: 90 // RFC 6066, Section 3 91 var nameList cryptobyte.String 92 if !extData.ReadUint16LengthPrefixed(&nameList) || nameList.Empty() { 93 return 94 } 95 for !nameList.Empty() { 96 var nameType uint8 97 var serverName cryptobyte.String 98 if !nameList.ReadUint8(&nameType) || 99 !nameList.ReadUint16LengthPrefixed(&serverName) || 100 serverName.Empty() { 101 return 102 } 103 if nameType != 0 { 104 continue 105 } 106 if len(info.ServerName) != 0 { 107 // Multiple names of the same name_type are prohibited. 108 return 109 } 110 info.ServerName = string(serverName) 111 // An SNI value may not include a trailing dot. 112 if strings.HasSuffix(info.ServerName, ".") { 113 return 114 } 115 } 116 case extensionStatusRequest: 117 // RFC 4366, Section 3.6 118 var statusType uint8 119 var ignored cryptobyte.String 120 if !extData.ReadUint8(&statusType) || 121 !extData.ReadUint16LengthPrefixed(&ignored) || 122 !extData.ReadUint16LengthPrefixed(&ignored) { 123 return 124 } 125 info.OCSPStapling = statusType == statusTypeOCSP 126 case extensionSupportedCurves: 127 // RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7 128 var curves cryptobyte.String 129 if !extData.ReadUint16LengthPrefixed(&curves) || curves.Empty() { 130 return 131 } 132 for !curves.Empty() { 133 var curve uint16 134 if !curves.ReadUint16(&curve) { 135 return 136 } 137 info.SupportedCurves = append(info.SupportedCurves, tls.CurveID(curve)) 138 } 139 case extensionSupportedPoints: 140 // RFC 4492, Section 5.1.2 141 if !readUint8LengthPrefixed(&extData, &info.SupportedPoints) || 142 len(info.SupportedPoints) == 0 { 143 return 144 } 145 case extensionSessionTicket: 146 // RFC 5077, Section 3.2 147 info.TicketSupported = true 148 extData.ReadBytes(&info.SessionTicket, len(extData)) 149 case extensionSignatureAlgorithms: 150 // RFC 5246, Section 7.4.1.4.1 151 var sigAndAlgs cryptobyte.String 152 if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { 153 return 154 } 155 for !sigAndAlgs.Empty() { 156 var sigAndAlg uint16 157 if !sigAndAlgs.ReadUint16(&sigAndAlg) { 158 return 159 } 160 info.SignatureSchemes = append( 161 info.SignatureSchemes, tls.SignatureScheme(sigAndAlg)) 162 } 163 case extensionSignatureAlgorithmsCert: 164 // RFC 8446, Section 4.2.3 165 var sigAndAlgs cryptobyte.String 166 if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { 167 return 168 } 169 for !sigAndAlgs.Empty() { 170 var sigAndAlg uint16 171 if !sigAndAlgs.ReadUint16(&sigAndAlg) { 172 return 173 } 174 info.SupportedSchemesCert = append( 175 info.SupportedSchemesCert, tls.SignatureScheme(sigAndAlg)) 176 } 177 case extensionRenegotiationInfo: 178 // RFC 5746, Section 3.2 179 if !readUint8LengthPrefixed(&extData, &info.SecureRenegotiation) { 180 return 181 } 182 info.SecureRenegotiationSupported = true 183 case extensionALPN: 184 // RFC 7301, Section 3.1 185 var protoList cryptobyte.String 186 if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() { 187 return 188 } 189 for !protoList.Empty() { 190 var proto cryptobyte.String 191 if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() { 192 return 193 } 194 info.SupportedProtos = append(info.SupportedProtos, string(proto)) 195 } 196 case extensionSCT: 197 // RFC 6962, Section 3.3.1 198 info.SCTs = true 199 case extensionSupportedVersions: 200 // RFC 8446, Section 4.2.1 201 var versList cryptobyte.String 202 if !extData.ReadUint8LengthPrefixed(&versList) || versList.Empty() { 203 return 204 } 205 for !versList.Empty() { 206 var vers uint16 207 if !versList.ReadUint16(&vers) { 208 return 209 } 210 info.SupportedVersions = append(info.SupportedVersions, vers) 211 } 212 case extensionCookie: 213 // RFC 8446, Section 4.2.2 214 if !readUint16LengthPrefixed(&extData, &info.Cookie) || 215 len(info.Cookie) == 0 { 216 return 217 } 218 case extensionKeyShare: 219 // RFC 8446, Section 4.2.8 220 var clientShares cryptobyte.String 221 if !extData.ReadUint16LengthPrefixed(&clientShares) { 222 return 223 } 224 for !clientShares.Empty() { 225 var ks KeyShare 226 if !clientShares.ReadUint16((*uint16)(&ks.Group)) || 227 !readUint16LengthPrefixed(&clientShares, &ks.Data) || 228 len(ks.Data) == 0 { 229 return 230 } 231 info.KeyShares = append(info.KeyShares, ks) 232 } 233 case extensionEarlyData: 234 // RFC 8446, Section 4.2.10 235 info.EarlyData = true 236 case extensionPSKModes: 237 // RFC 8446, Section 4.2.9 238 if !readUint8LengthPrefixed(&extData, &info.PSKModes) { 239 return 240 } 241 case extensionPreSharedKey: 242 // RFC 8446, Section 4.2.11 243 if !extensions.Empty() { 244 return // pre_shared_key must be the last extension 245 } 246 var identities cryptobyte.String 247 if !extData.ReadUint16LengthPrefixed(&identities) || identities.Empty() { 248 return 249 } 250 for !identities.Empty() { 251 var psk PSKIdentity 252 if !readUint16LengthPrefixed(&identities, &psk.label) || 253 !identities.ReadUint32(&psk.obfuscatedTicketAge) || 254 len(psk.label) == 0 { 255 return 256 } 257 info.PSKIdentities = append(info.PSKIdentities, psk) 258 } 259 var binders cryptobyte.String 260 if !extData.ReadUint16LengthPrefixed(&binders) || binders.Empty() { 261 return 262 } 263 for !binders.Empty() { 264 var binder []byte 265 if !readUint8LengthPrefixed(&binders, &binder) || 266 len(binder) == 0 { 267 return 268 } 269 info.PSKBinders = append(info.PSKBinders, binder) 270 } 271 default: 272 // Ignore unknown extensions. 273 continue 274 } 275 276 if !extData.Empty() { 277 return 278 } 279 } 280 281 return 282 } 283 284 // allKnownVersions is all the TLS versions this package knows. 285 var allKnownVersions = []uint16{ 286 tls.VersionTLS13, 287 tls.VersionTLS12, 288 tls.VersionTLS11, 289 tls.VersionTLS10, 290 } 291 292 // supportedVersionsFromMax returns a list of supported versions derived from a 293 // legacy maximum version value. Note that only versions supported by this 294 // library are returned. Any newer peer will use allKnownVersions anyway. 295 func supportedVersionsFromMax(maxVersion uint16) []uint16 { 296 versions := make([]uint16, 0, len(allKnownVersions)) 297 for _, v := range allKnownVersions { 298 if v > maxVersion { 299 continue 300 } 301 versions = append(versions, v) 302 } 303 return versions 304 } 305 306 // readUint8LengthPrefixed acts like s.ReadUint8LengthPrefixed, but targets a 307 // []byte instead of a cryptobyte.String. 308 func readUint8LengthPrefixed(s *cryptobyte.String, out *[]byte) bool { 309 return s.ReadUint8LengthPrefixed((*cryptobyte.String)(out)) 310 } 311 312 // readUint16LengthPrefixed acts like s.ReadUint16LengthPrefixed, but targets a 313 // []byte instead of a cryptobyte.String. 314 func readUint16LengthPrefixed(s *cryptobyte.String, out *[]byte) bool { 315 return s.ReadUint16LengthPrefixed((*cryptobyte.String)(out)) 316 } 317 318 // TLS extension numbers 319 const ( 320 extensionServerName uint16 = 0 321 extensionStatusRequest uint16 = 5 322 extensionSupportedCurves uint16 = 10 // supported_groups in TLS 1.3, see RFC 8446, Section 4.2.7 323 extensionSupportedPoints uint16 = 11 324 extensionSignatureAlgorithms uint16 = 13 325 extensionALPN uint16 = 16 326 extensionSCT uint16 = 18 327 extensionSessionTicket uint16 = 35 328 extensionPreSharedKey uint16 = 41 329 extensionEarlyData uint16 = 42 330 extensionSupportedVersions uint16 = 43 331 extensionCookie uint16 = 44 332 extensionPSKModes uint16 = 45 333 extensionCertificateAuthorities uint16 = 47 334 extensionSignatureAlgorithmsCert uint16 = 50 335 extensionKeyShare uint16 = 51 336 extensionRenegotiationInfo uint16 = 0xff01 337 ) 338 339 // TLS signaling cipher suite values 340 const ( 341 scsvRenegotiation uint16 = 0x00ff 342 ) 343 344 // TLS CertificateStatusType (RFC 3546) 345 const ( 346 statusTypeOCSP uint8 = 1 347 ) 348 349 // KeyShare is a TLS 1.3 Key Share. See RFC 8446, Section 4.2.8. 350 type KeyShare struct { 351 Group tls.CurveID 352 Data []byte 353 } 354 355 // PSKIdentity is a TLS 1.3 PSK Identity. 356 // Can be a Session Ticket, or a reference to a saved 357 // session. See RFC 8446, Section 4.2.11. 358 type PSKIdentity struct { 359 label []byte 360 obfuscatedTicketAge uint32 361 }