Replace hs->needs_psk_binder with an output parameter.

May not be strictly necessary, but similarly easier to reason about when
we need to interweave multiple ClientHellos.

Bug: 275
Change-Id: I9f85787860f3e8ce1653331ce52343d5bf5def23
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47992
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/handshake.cc b/ssl/handshake.cc
index 9133e16..1994465 100644
--- a/ssl/handshake.cc
+++ b/ssl/handshake.cc
@@ -129,7 +129,6 @@
       ech_present(false),
       ech_is_inner_present(false),
       scts_requested(false),
-      needs_psk_binder(false),
       handshake_finalized(false),
       accept_psk_mode(false),
       cert_request(false),
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index 710b036..e2c3dd9 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -310,10 +310,12 @@
 
   size_t header_len =
       SSL_is_dtls(ssl) ? DTLS1_HM_HEADER_LENGTH : SSL3_HM_HEADER_LENGTH;
+  bool needs_psk_binder;
   if (!ssl_write_client_cipher_list(hs, &body) ||
       !CBB_add_u8(&body, 1 /* one compression method */) ||
       !CBB_add_u8(&body, 0 /* null compression */) ||
-      !ssl_add_clienthello_tlsext(hs, &body, header_len + CBB_len(&body))) {
+      !ssl_add_clienthello_tlsext(hs, &body, &needs_psk_binder,
+                                  header_len + CBB_len(&body))) {
     return false;
   }
 
@@ -324,7 +326,7 @@
 
   // Now that the length prefixes have been computed, fill in the placeholder
   // PSK binder.
-  if (hs->needs_psk_binder &&
+  if (needs_psk_binder &&
       !tls13_write_psk_binder(hs, MakeSpan(msg))) {
     return false;
   }
diff --git a/ssl/internal.h b/ssl/internal.h
index 8d7e493..250beb1 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1866,10 +1866,6 @@
   // scts_requested is true if the SCT extension is in the ClientHello.
   bool scts_requested : 1;
 
-  // needs_psk_binder is true if the ClientHello has a placeholder PSK binder to
-  // be filled in.
-  bool needs_psk_binder : 1;
-
   // handshake_finalized is true once the handshake has completed, at which
   // point accessors should use the established state.
   bool handshake_finalized : 1;
@@ -3167,8 +3163,11 @@
 // ssl_add_clienthello_tlsext writes ClientHello extensions to |out|. It returns
 // true on success and false on failure. The |header_len| argument is the length
 // of the ClientHello written so far and is used to compute the padding length.
-// (It does not include the record header.)
-bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len);
+// (It does not include the record header.) On success, if
+// |*out_needs_psk_binder| is true, the last ClientHello extension was the
+// pre_shared_key extension and needs a PSK binder filled in.
+bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out,
+                                bool *out_needs_psk_binder, size_t header_len);
 
 bool ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out);
 bool ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index bd246f3..d46241e 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -1944,9 +1944,11 @@
   return 15 + ssl->session->ticket.size() + binder_len;
 }
 
-static bool ext_pre_shared_key_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+static bool ext_pre_shared_key_add_clienthello(const SSL_HANDSHAKE *hs,
+                                               CBB *out,
+                                               bool *out_needs_binder) {
   const SSL *const ssl = hs->ssl;
-  hs->needs_psk_binder = false;
+  *out_needs_binder = false;
   if (hs->max_version < TLS1_3_VERSION || ssl->session == nullptr ||
       ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION) {
     return true;
@@ -1984,7 +1986,7 @@
     return false;
   }
 
-  hs->needs_psk_binder = true;
+  *out_needs_binder = true;
   return CBB_flush(out);
 }
 
@@ -3242,9 +3244,10 @@
 }
 
 bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out,
-                                size_t header_len) {
+                                bool *out_needs_psk_binder, size_t header_len) {
   SSL *const ssl = hs->ssl;
   CBB extensions;
+  *out_needs_psk_binder = false;
   if (!CBB_add_u16_length_prefixed(out, &extensions)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return false;
@@ -3355,7 +3358,8 @@
   }
 
   // The PSK extension must be last, including after the padding.
-  if (!ext_pre_shared_key_add_clienthello(hs, &extensions)) {
+  if (!ext_pre_shared_key_add_clienthello(hs, &extensions,
+                                          out_needs_psk_binder)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return false;
   }