MCPcopy
hub / github.com/XTLS/REALITY / decodeInnerClientHello

Function decodeInnerClientHello

ech.go:286–421  ·  view source on GitHub ↗
(outer *clientHelloMsg, encoded []byte)

Source from the content-addressed store, hash-verified

284}
285
286func decodeInnerClientHello(outer *clientHelloMsg, encoded []byte) (*clientHelloMsg, error) {
287 // Reconstructing the inner client hello from its encoded form is somewhat
288 // complicated. It is missing its header (message type and length), session
289 // ID, and the extensions may be compressed. Since we need to put the
290 // extensions back in the same order as they were in the raw outer hello,
291 // and since we don't store the raw extensions, or the order we parsed them
292 // in, we need to reparse the raw extensions from the outer hello in order
293 // to properly insert them into the inner hello. This _should_ result in raw
294 // bytes which match the hello as it was generated by the client.
295 innerReader := cryptobyte.String(encoded)
296 var versionAndRandom, sessionID, cipherSuites, compressionMethods []byte
297 var extensions cryptobyte.String
298 if !innerReader.ReadBytes(&versionAndRandom, 2+32) ||
299 !readUint8LengthPrefixed(&innerReader, &sessionID) ||
300 len(sessionID) != 0 ||
301 !readUint16LengthPrefixed(&innerReader, &cipherSuites) ||
302 !readUint8LengthPrefixed(&innerReader, &compressionMethods) ||
303 !innerReader.ReadUint16LengthPrefixed(&extensions) {
304 return nil, errors.New("tls: invalid inner client hello")
305 }
306
307 // The specification says we must verify that the trailing padding is all
308 // zeros. This is kind of weird for TLS messages, where we generally just
309 // throw away any trailing garbage.
310 for _, p := range innerReader {
311 if p != 0 {
312 return nil, errors.New("tls: invalid inner client hello")
313 }
314 }
315
316 rawOuterExts, err := extractRawExtensions(outer)
317 if err != nil {
318 return nil, err
319 }
320
321 recon := cryptobyte.NewBuilder(nil)
322 recon.AddUint8(typeClientHello)
323 recon.AddUint24LengthPrefixed(func(recon *cryptobyte.Builder) {
324 recon.AddBytes(versionAndRandom)
325 recon.AddUint8LengthPrefixed(func(recon *cryptobyte.Builder) {
326 recon.AddBytes(outer.sessionId)
327 })
328 recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) {
329 recon.AddBytes(cipherSuites)
330 })
331 recon.AddUint8LengthPrefixed(func(recon *cryptobyte.Builder) {
332 recon.AddBytes(compressionMethods)
333 })
334 recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) {
335 for !extensions.Empty() {
336 var extension uint16
337 var extData cryptobyte.String
338 if !extensions.ReadUint16(&extension) ||
339 !extensions.ReadUint16LengthPrefixed(&extData) {
340 recon.SetError(errors.New("tls: invalid inner client hello"))
341 return
342 }
343 if extension == extensionECHOuterExtensions {

Callers 2

doHelloRetryRequestMethod · 0.85
processECHClientHelloMethod · 0.85

Calls 6

unmarshalMethod · 0.95
readUint8LengthPrefixedFunction · 0.85
readUint16LengthPrefixedFunction · 0.85
extractRawExtensionsFunction · 0.85
BytesMethod · 0.80
StringMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…