processHelloRetryRequest handles the HRR in hs.serverHello, modifies and resends hs.hello, and reads the new ServerHello into hs.serverHello.
()
| 233 | // processHelloRetryRequest handles the HRR in hs.serverHello, modifies and |
| 234 | // resends hs.hello, and reads the new ServerHello into hs.serverHello. |
| 235 | func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { |
| 236 | c := hs.c |
| 237 | |
| 238 | // The first ClientHello gets double-hashed into the transcript upon a |
| 239 | // HelloRetryRequest. (The idea is that the server might offload transcript |
| 240 | // storage to the client in the cookie.) See RFC 8446, Section 4.4.1. |
| 241 | chHash := hs.transcript.Sum(nil) |
| 242 | hs.transcript.Reset() |
| 243 | hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) |
| 244 | hs.transcript.Write(chHash) |
| 245 | if err := transcriptMsg(hs.serverHello, hs.transcript); err != nil { |
| 246 | return err |
| 247 | } |
| 248 | |
| 249 | var isInnerHello bool |
| 250 | hello := hs.hello |
| 251 | if hs.echContext != nil { |
| 252 | chHash = hs.echContext.innerTranscript.Sum(nil) |
| 253 | hs.echContext.innerTranscript.Reset() |
| 254 | hs.echContext.innerTranscript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) |
| 255 | hs.echContext.innerTranscript.Write(chHash) |
| 256 | |
| 257 | if hs.serverHello.encryptedClientHello != nil { |
| 258 | if len(hs.serverHello.encryptedClientHello) != 8 { |
| 259 | hs.c.sendAlert(alertDecodeError) |
| 260 | return errors.New("tls: malformed encrypted client hello extension") |
| 261 | } |
| 262 | |
| 263 | confTranscript := cloneHash(hs.echContext.innerTranscript, hs.suite.hash) |
| 264 | hrrHello := make([]byte, len(hs.serverHello.original)) |
| 265 | copy(hrrHello, hs.serverHello.original) |
| 266 | hrrHello = bytes.Replace(hrrHello, hs.serverHello.encryptedClientHello, make([]byte, 8), 1) |
| 267 | confTranscript.Write(hrrHello) |
| 268 | h := hs.suite.hash.New |
| 269 | prk, err := hkdf.Extract(h, hs.echContext.innerHello.random, nil) |
| 270 | if err != nil { |
| 271 | c.sendAlert(alertInternalError) |
| 272 | return err |
| 273 | } |
| 274 | acceptConfirmation := tls13.ExpandLabel(h, prk, "hrr ech accept confirmation", confTranscript.Sum(nil), 8) |
| 275 | if subtle.ConstantTimeCompare(acceptConfirmation, hs.serverHello.encryptedClientHello) == 1 { |
| 276 | hello = hs.echContext.innerHello |
| 277 | c.serverName = c.config.ServerName |
| 278 | isInnerHello = true |
| 279 | c.echAccepted = true |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | if err := transcriptMsg(hs.serverHello, hs.echContext.innerTranscript); err != nil { |
| 284 | return err |
| 285 | } |
| 286 | } else if hs.serverHello.encryptedClientHello != nil { |
| 287 | // Unsolicited ECH extension should be rejected |
| 288 | c.sendAlert(alertUnsupportedExtension) |
| 289 | return errors.New("tls: unexpected encrypted client hello extension in serverHello") |
| 290 | } |
| 291 | |
| 292 | // The only HelloRetryRequest extensions we support are key_share and |
no test coverage detected