Adding HelloRetryRequest.
[Tests added by davidben.]
Change-Id: I0d54a4f8b8fe91b348ff22658d95340cdb48b089
Reviewed-on: https://boringssl-review.googlesource.com/8850
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index f76d9f0..7549240 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -300,12 +300,9 @@
#endif
};
-/* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
- * list of allowed group IDs. If |get_peer_groups| is non-zero, return the
- * peer's group list. Otherwise, return the preferred list. */
-static void tls1_get_grouplist(SSL *ssl, int get_peer_groups,
- const uint16_t **out_group_ids,
- size_t *out_group_ids_len) {
+void tls1_get_grouplist(SSL *ssl, int get_peer_groups,
+ const uint16_t **out_group_ids,
+ size_t *out_group_ids_len) {
if (get_peer_groups) {
/* Only clients send a supported group list, so this function is only
* called on the server. */
@@ -1973,7 +1970,24 @@
const uint16_t *groups;
size_t groups_len;
- tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
+ if (ssl->s3->hs->retry_group) {
+ /* Append the new key share to the old list. */
+ if (!CBB_add_bytes(&kse_bytes, ssl->s3->hs->key_share_bytes,
+ ssl->s3->hs->key_share_bytes_len)) {
+ return 0;
+ }
+ OPENSSL_free(ssl->s3->hs->key_share_bytes);
+ ssl->s3->hs->key_share_bytes = NULL;
+
+ groups = &ssl->s3->hs->retry_group;
+ groups_len = 1;
+ } else {
+ tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
+ /* Only send the top two preferred key shares. */
+ if (groups_len > 2) {
+ groups_len = 2;
+ }
+ }
ssl->s3->hs->groups = OPENSSL_malloc(groups_len * sizeof(SSL_ECDH_CTX));
if (ssl->s3->hs->groups == NULL) {
@@ -1996,6 +2010,17 @@
}
}
+ if (!ssl->s3->hs->retry_group) {
+ /* Save the contents of the extension to repeat it in the second
+ * ClientHello. */
+ ssl->s3->hs->key_share_bytes_len = CBB_len(&kse_bytes);
+ ssl->s3->hs->key_share_bytes = BUF_memdup(CBB_data(&kse_bytes),
+ CBB_len(&kse_bytes));
+ if (ssl->s3->hs->key_share_bytes == NULL) {
+ return 0;
+ }
+ }
+
return CBB_flush(out);
}
@@ -2030,16 +2055,12 @@
return 0;
}
- for (size_t i = 0; i < ssl->s3->hs->groups_len; i++) {
- SSL_ECDH_CTX_cleanup(&ssl->s3->hs->groups[i]);
- }
- OPENSSL_free(ssl->s3->hs->groups);
- ssl->s3->hs->groups = NULL;
-
+ ssl_handshake_clear_groups(ssl->s3->hs);
return 1;
}
-int ext_key_share_parse_clienthello(SSL *ssl, uint8_t **out_secret,
+int ext_key_share_parse_clienthello(SSL *ssl, int *out_found,
+ uint8_t **out_secret,
size_t *out_secret_len, uint8_t *out_alert,
CBS *contents) {
uint16_t group_id;
@@ -2049,7 +2070,7 @@
return 0;
}
- int found = 0;
+ *out_found = 0;
while (CBS_len(&key_shares) > 0) {
uint16_t id;
CBS peer_key;
@@ -2058,7 +2079,7 @@
return 0;
}
- if (id != group_id || found) {
+ if (id != group_id || *out_found) {
continue;
}
@@ -2078,10 +2099,10 @@
}
SSL_ECDH_CTX_cleanup(&group);
- found = 1;
+ *out_found = 1;
}
- return found;
+ return 1;
}
int ext_key_share_add_serverhello(SSL *ssl, CBB *out) {