Generalizing curves to groups in preparation for TLS 1.3.

The 'elliptic_curves' extension is being renamed to 'supported_groups'
in the TLS 1.3 draft, and most of the curve-specific methods are
generalized to groups/group IDs.

Change-Id: Icd1a1cf7365c8a4a64ae601993dc4273802610fb
Reviewed-on: https://boringssl-review.googlesource.com/7955
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 33d2710..3e7fad8 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1839,9 +1839,9 @@
 OPENSSL_EXPORT int SSL_set1_curves(SSL *ssl, const int *curves,
                                    size_t curves_len);
 
-/* SSL_get_curve_name returns a human-readable name for the elliptic curve
- * specified by the given TLS curve id, or NULL if the curve if unknown. */
-OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t curve_id);
+/* SSL_get_curve_name returns a human-readable name for the group specified by
+ * the given TLS group id, or NULL if the group is unknown. */
+OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t group_id);
 
 
 /* Multiplicative Diffie-Hellman.
@@ -3795,9 +3795,9 @@
   /* SRTP profiles we are willing to do from RFC 5764 */
   STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
 
-  /* EC extension values inherited by SSL structure */
-  size_t tlsext_ellipticcurvelist_length;
-  uint16_t *tlsext_ellipticcurvelist;
+  /* Supported group values inherited by SSL structure */
+  size_t supported_group_list_len;
+  uint16_t *supported_group_list;
 
   /* The client's Channel ID private key. */
   EVP_PKEY *tlsext_channel_id_private;
@@ -3958,8 +3958,8 @@
   char *tlsext_hostname;
   /* RFC4507 session ticket expected to be received or sent */
   int tlsext_ticket_expected;
-  size_t tlsext_ellipticcurvelist_length;
-  uint16_t *tlsext_ellipticcurvelist; /* our list */
+  size_t supported_group_list_len;
+  uint16_t *supported_group_list; /* our list */
 
   SSL_CTX *initial_ctx; /* initial ctx, used to store sessions */
 
@@ -4205,11 +4205,11 @@
     /* ocsp_stapling_requested is true if a client requested OCSP stapling. */
     unsigned ocsp_stapling_requested:1;
 
-    /* Server-only: peer_ellipticcurvelist contains the EC curve IDs advertised
-     * by the peer. This is only set on the server's end. The server does not
-     * advertise this extension to the client. */
-    uint16_t *peer_ellipticcurvelist;
-    size_t peer_ellipticcurvelist_length;
+    /* Server-only: peer_supported_group_list contains the supported group IDs
+     * advertised by the peer. This is only set on the server's end. The server
+     * does not advertise this extension to the client. */
+    uint16_t *peer_supported_group_list;
+    size_t peer_supported_group_list_len;
 
     /* extended_master_secret indicates whether the extended master secret
      * computation is used in this handshake. Note that this is different from
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index e0f1399..df17375 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -196,8 +196,10 @@
 /* ExtensionType values from RFC6091 */
 #define TLSEXT_TYPE_cert_type 9
 
+/* ExtensionType values from draft-ietf-tls-tls13-latest */
+#define TLSEXT_TYPE_supported_groups 10
+
 /* ExtensionType values from RFC4492 */
-#define TLSEXT_TYPE_elliptic_curves 10
 #define TLSEXT_TYPE_ec_point_formats 11
 
 /* ExtensionType value from RFC5054 */
diff --git a/ssl/internal.h b/ssl/internal.h
index acd9739..f3b6d01 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -527,19 +527,19 @@
 int ssl3_update_handshake_hash(SSL *ssl, const uint8_t *in, size_t in_len);
 
 
-/* ECDH curves. */
+/* ECDH groups. */
 
-#define SSL_CURVE_SECP256R1 23
-#define SSL_CURVE_SECP384R1 24
-#define SSL_CURVE_SECP521R1 25
-#define SSL_CURVE_X25519 29
-#define SSL_CURVE_CECPQ1 65165
+#define SSL_GROUP_SECP256R1 23
+#define SSL_GROUP_SECP384R1 24
+#define SSL_GROUP_SECP521R1 25
+#define SSL_GROUP_X25519 29
+#define SSL_GROUP_CECPQ1 65165
 
 /* An SSL_ECDH_METHOD is an implementation of ECDH-like key exchanges for
  * TLS. */
 struct ssl_ecdh_method_st {
   int nid;
-  uint16_t curve_id;
+  uint16_t group_id;
   const char name[8];
 
   /* cleanup releases state in |ctx|. */
@@ -579,14 +579,14 @@
   int (*add_key)(CBB *cbb, CBB *out_contents);
 } /* SSL_ECDH_METHOD */;
 
-/* ssl_nid_to_curve_id looks up the curve corresponding to |nid|. On success, it
- * sets |*out_curve_id| to the curve ID and returns one. Otherwise, it returns
+/* ssl_nid_to_group_id looks up the group corresponding to |nid|. On success, it
+ * sets |*out_group_id| to the group ID and returns one. Otherwise, it returns
  * zero. */
-int ssl_nid_to_curve_id(uint16_t *out_curve_id, int nid);
+int ssl_nid_to_group_id(uint16_t *out_group_id, int nid);
 
-/* SSL_ECDH_CTX_init sets up |ctx| for use with curve |curve_id|. It returns one
+/* SSL_ECDH_CTX_init sets up |ctx| for use with curve |group_id|. It returns one
  * on success and zero on error. */
-int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t curve_id);
+int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id);
 
 /* SSL_ECDH_CTX_init_for_dhe sets up |ctx| for use with legacy DHE-based ciphers
  * where the server specifies a group. It takes ownership of |params|. */
@@ -1190,21 +1190,21 @@
 
 char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx);
 
-/* tls1_check_curve_id returns one if |curve_id| is consistent with both our
- * and the peer's curve preferences. Note: if called as the client, only our
+/* tls1_check_group_id returns one if |group_id| is consistent with both our
+ * and the peer's group preferences. Note: if called as the client, only our
  * preferences are checked; the peer (the server) does not send preferences. */
-int tls1_check_curve_id(SSL *ssl, uint16_t curve_id);
+int tls1_check_group_id(SSL *ssl, uint16_t group_id);
 
-/* tls1_get_shared_curve sets |*out_curve_id| to the first preferred shared
- * curve between client and server preferences and returns one. If none may be
+/* tls1_get_shared_group sets |*out_group_id| to the first preferred shared
+ * group between client and server preferences and returns one. If none may be
  * found, it returns zero. */
-int tls1_get_shared_curve(SSL *ssl, uint16_t *out_curve_id);
+int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id);
 
 /* tls1_set_curves converts the array of |ncurves| NIDs pointed to by |curves|
- * into a newly allocated array of TLS curve IDs. On success, the function
- * returns one and writes the array to |*out_curve_ids| and its size to
- * |*out_curve_ids_len|. Otherwise, it returns zero. */
-int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
+ * into a newly allocated array of TLS group IDs. On success, the function
+ * returns one and writes the array to |*out_group_ids| and its size to
+ * |*out_group_ids_len|. Otherwise, it returns zero. */
+int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len,
                     const int *curves, size_t ncurves);
 
 /* tls1_check_ec_cert returns one if |x| is an ECC certificate with curve and
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 39aea3c..51274f7 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1137,26 +1137,26 @@
     ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
   } else if (alg_k & SSL_kECDHE) {
     /* Parse the server parameters. */
-    uint8_t curve_type;
-    uint16_t curve_id;
+    uint8_t group_type;
+    uint16_t group_id;
     CBS point;
-    if (!CBS_get_u8(&server_key_exchange, &curve_type) ||
-        curve_type != NAMED_CURVE_TYPE ||
-        !CBS_get_u16(&server_key_exchange, &curve_id)) {
+    if (!CBS_get_u8(&server_key_exchange, &group_type) ||
+        group_type != NAMED_CURVE_TYPE ||
+        !CBS_get_u16(&server_key_exchange, &group_id)) {
       al = SSL_AD_DECODE_ERROR;
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
       goto f_err;
     }
-    ssl->session->key_exchange_info = curve_id;
+    ssl->session->key_exchange_info = group_id;
 
-    /* Ensure the curve is consistent with preferences. */
-    if (!tls1_check_curve_id(ssl, curve_id)) {
+    /* Ensure the group is consistent with preferences. */
+    if (!tls1_check_group_id(ssl, group_id)) {
       al = SSL_AD_ILLEGAL_PARAMETER;
       OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
       goto f_err;
     }
 
-    if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, curve_id)) {
+    if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id)) {
       goto err;
     }
     if (!SSL_ECDH_CTX_get_key(&ssl->s3->tmp.ecdh_ctx, &server_key_exchange,
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 7df046f..4cf5aa3 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -220,7 +220,7 @@
 
   sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
   OPENSSL_free(ssl->s3->tmp.certificate_types);
-  OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
+  OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
   OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint);
   ssl3_free_handshake_buffer(ssl);
   ssl3_free_handshake_hash(ssl);
@@ -382,14 +382,14 @@
 }
 
 int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves, size_t curves_len) {
-  return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
-                         &ctx->tlsext_ellipticcurvelist_length, curves,
+  return tls1_set_curves(&ctx->supported_group_list,
+                         &ctx->supported_group_list_len, curves,
                          curves_len);
 }
 
 int SSL_set1_curves(SSL *ssl, const int *curves, size_t curves_len) {
-  return tls1_set_curves(&ssl->tlsext_ellipticcurvelist,
-                         &ssl->tlsext_ellipticcurvelist_length, curves,
+  return tls1_set_curves(&ssl->supported_group_list,
+                         &ssl->supported_group_list_len, curves,
                          curves_len);
 }
 
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 17dc15b..1682bb2 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1214,19 +1214,19 @@
         goto err;
       }
     } else if (alg_k & SSL_kECDHE) {
-      /* Determine the curve to use. */
-      uint16_t curve_id;
-      if (!tls1_get_shared_curve(ssl, &curve_id)) {
+      /* Determine the group to use. */
+      uint16_t group_id;
+      if (!tls1_get_shared_group(ssl, &group_id)) {
         OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_ECDH_KEY);
         ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
         goto err;
       }
-      ssl->session->key_exchange_info = curve_id;
+      ssl->session->key_exchange_info = group_id;
 
       /* Set up ECDH, generate a key, and emit the public half. */
-      if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, curve_id) ||
+      if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) ||
           !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) ||
-          !CBB_add_u16(&cbb, curve_id) ||
+          !CBB_add_u16(&cbb, group_id) ||
           !SSL_ECDH_CTX_add_key(&ssl->s3->tmp.ecdh_ctx, &cbb, &child) ||
           !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
         goto err;
diff --git a/ssl/ssl_ecdh.c b/ssl/ssl_ecdh.c
index 04ecd39..1236cd3 100644
--- a/ssl/ssl_ecdh.c
+++ b/ssl/ssl_ecdh.c
@@ -451,7 +451,7 @@
 static const SSL_ECDH_METHOD kMethods[] = {
     {
         NID_X9_62_prime256v1,
-        SSL_CURVE_SECP256R1,
+        SSL_GROUP_SECP256R1,
         "P-256",
         ssl_ec_point_cleanup,
         ssl_ec_point_offer,
@@ -462,7 +462,7 @@
     },
     {
         NID_secp384r1,
-        SSL_CURVE_SECP384R1,
+        SSL_GROUP_SECP384R1,
         "P-384",
         ssl_ec_point_cleanup,
         ssl_ec_point_offer,
@@ -473,7 +473,7 @@
     },
     {
         NID_secp521r1,
-        SSL_CURVE_SECP521R1,
+        SSL_GROUP_SECP521R1,
         "P-521",
         ssl_ec_point_cleanup,
         ssl_ec_point_offer,
@@ -484,7 +484,7 @@
     },
     {
         NID_X25519,
-        SSL_CURVE_X25519,
+        SSL_GROUP_X25519,
         "X25519",
         ssl_x25519_cleanup,
         ssl_x25519_offer,
@@ -495,7 +495,7 @@
     },
     {
         NID_cecpq1,
-        SSL_CURVE_CECPQ1,
+        SSL_GROUP_CECPQ1,
         "CECPQ1",
         ssl_cecpq1_cleanup,
         ssl_cecpq1_offer,
@@ -506,10 +506,10 @@
     },
 };
 
-static const SSL_ECDH_METHOD *method_from_curve_id(uint16_t curve_id) {
+static const SSL_ECDH_METHOD *method_from_group_id(uint16_t group_id) {
   size_t i;
   for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
-    if (kMethods[i].curve_id == curve_id) {
+    if (kMethods[i].group_id == group_id) {
       return &kMethods[i];
     }
   }
@@ -526,27 +526,27 @@
   return NULL;
 }
 
-const char* SSL_get_curve_name(uint16_t curve_id) {
-  const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
+const char* SSL_get_curve_name(uint16_t group_id) {
+  const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
   if (method == NULL) {
     return NULL;
   }
   return method->name;
 }
 
-int ssl_nid_to_curve_id(uint16_t *out_curve_id, int nid) {
+int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
   const SSL_ECDH_METHOD *method = method_from_nid(nid);
   if (method == NULL) {
     return 0;
   }
-  *out_curve_id = method->curve_id;
+  *out_group_id = method->group_id;
   return 1;
 }
 
-int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t curve_id) {
+int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id) {
   SSL_ECDH_CTX_cleanup(ctx);
 
-  const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
+  const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
   if (method == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
     return 0;
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 74c2d26..fd8c04c 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -341,7 +341,7 @@
   sk_X509_NAME_pop_free(ctx->client_CA, X509_NAME_free);
   sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles);
   OPENSSL_free(ctx->psk_identity_hint);
-  OPENSSL_free(ctx->tlsext_ellipticcurvelist);
+  OPENSSL_free(ctx->supported_group_list);
   OPENSSL_free(ctx->alpn_client_proto_list);
   OPENSSL_free(ctx->ocsp_response);
   OPENSSL_free(ctx->signed_cert_timestamp_list);
@@ -403,14 +403,14 @@
   CRYPTO_refcount_inc(&ctx->references);
   ssl->initial_ctx = ctx;
 
-  if (ctx->tlsext_ellipticcurvelist) {
-    ssl->tlsext_ellipticcurvelist =
-        BUF_memdup(ctx->tlsext_ellipticcurvelist,
-                   ctx->tlsext_ellipticcurvelist_length * 2);
-    if (!ssl->tlsext_ellipticcurvelist) {
+  if (ctx->supported_group_list) {
+    ssl->supported_group_list =
+        BUF_memdup(ctx->supported_group_list,
+                   ctx->supported_group_list_len * 2);
+    if (!ssl->supported_group_list) {
       goto err;
     }
-    ssl->tlsext_ellipticcurvelist_length = ctx->tlsext_ellipticcurvelist_length;
+    ssl->supported_group_list_len = ctx->supported_group_list_len;
   }
 
   if (ssl->ctx->alpn_client_proto_list) {
@@ -499,7 +499,7 @@
 
   OPENSSL_free(ssl->tlsext_hostname);
   SSL_CTX_free(ssl->initial_ctx);
-  OPENSSL_free(ssl->tlsext_ellipticcurvelist);
+  OPENSSL_free(ssl->supported_group_list);
   OPENSSL_free(ssl->alpn_client_proto_list);
   EVP_PKEY_free(ssl->tlsext_channel_id_private);
   OPENSSL_free(ssl->psk_identity_hint);
@@ -1705,7 +1705,7 @@
       mask_a |= SSL_aRSA;
     } else if (ssl_private_key_type(ssl) == EVP_PKEY_EC) {
       /* An ECC certificate may be usable for ECDSA cipher suites depending on
-       * the key usage extension and on the client's curve preferences. */
+       * the key usage extension and on the client's group preferences. */
       X509 *x = ssl->cert->x509;
       /* This call populates extension flags (ex_flags). */
       X509_check_purpose(x, -1, 0);
@@ -1722,9 +1722,9 @@
     mask_k |= SSL_kDHE;
   }
 
-  /* Check for a shared curve to consider ECDHE ciphers. */
+  /* Check for a shared group to consider ECDHE ciphers. */
   uint16_t unused;
-  if (tls1_get_shared_curve(ssl, &unused)) {
+  if (tls1_get_shared_group(ssl, &unused)) {
     mask_k |= SSL_kECDHE;
   }
 
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index eac9579..16cac15 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -291,77 +291,77 @@
   return 0;
 }
 
-static const uint16_t eccurves_default[] = {
-    SSL_CURVE_X25519,
-    SSL_CURVE_SECP256R1,
-    SSL_CURVE_SECP384R1,
+static const uint16_t kDefaultGroups[] = {
+    SSL_GROUP_X25519,
+    SSL_GROUP_SECP256R1,
+    SSL_GROUP_SECP384R1,
 #if defined(BORINGSSL_ANDROID_SYSTEM)
-    SSL_CURVE_SECP521R1,
+    SSL_GROUP_SECP521R1,
 #endif
 };
 
-/* tls1_get_curvelist sets |*out_curve_ids| and |*out_curve_ids_len| to the
- * list of allowed curve IDs. If |get_peer_curves| is non-zero, return the
- * peer's curve list. Otherwise, return the preferred list. */
-static void tls1_get_curvelist(SSL *ssl, int get_peer_curves,
-                               const uint16_t **out_curve_ids,
-                               size_t *out_curve_ids_len) {
-  if (get_peer_curves) {
-    /* Only clients send a curve list, so this function is only called
-     * on the server. */
+/* 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) {
+  if (get_peer_groups) {
+    /* Only clients send a supported group list, so this function is only
+     * called on the server. */
     assert(ssl->server);
-    *out_curve_ids = ssl->s3->tmp.peer_ellipticcurvelist;
-    *out_curve_ids_len = ssl->s3->tmp.peer_ellipticcurvelist_length;
+    *out_group_ids = ssl->s3->tmp.peer_supported_group_list;
+    *out_group_ids_len = ssl->s3->tmp.peer_supported_group_list_len;
     return;
   }
 
-  *out_curve_ids = ssl->tlsext_ellipticcurvelist;
-  *out_curve_ids_len = ssl->tlsext_ellipticcurvelist_length;
-  if (!*out_curve_ids) {
-    *out_curve_ids = eccurves_default;
-    *out_curve_ids_len = sizeof(eccurves_default) / sizeof(eccurves_default[0]);
+  *out_group_ids = ssl->supported_group_list;
+  *out_group_ids_len = ssl->supported_group_list_len;
+  if (!*out_group_ids) {
+    *out_group_ids = kDefaultGroups;
+    *out_group_ids_len = sizeof(kDefaultGroups) / sizeof(kDefaultGroups[0]);
   }
 }
 
-int tls1_get_shared_curve(SSL *ssl, uint16_t *out_curve_id) {
-  const uint16_t *curves, *peer_curves, *pref, *supp;
-  size_t curves_len, peer_curves_len, pref_len, supp_len, i, j;
+int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id) {
+  const uint16_t *groups, *peer_groups, *pref, *supp;
+  size_t groups_len, peer_groups_len, pref_len, supp_len, i, j;
 
   /* Can't do anything on client side */
   if (ssl->server == 0) {
     return 0;
   }
 
-  tls1_get_curvelist(ssl, 0 /* local curves */, &curves, &curves_len);
-  tls1_get_curvelist(ssl, 1 /* peer curves */, &peer_curves, &peer_curves_len);
+  tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
+  tls1_get_grouplist(ssl, 1 /* peer groups */, &peer_groups, &peer_groups_len);
 
-  if (peer_curves_len == 0) {
-    /* Clients are not required to send a supported_curves extension. In this
-     * case, the server is free to pick any curve it likes. See RFC 4492,
+  if (peer_groups_len == 0) {
+    /* Clients are not required to send a supported_groups extension. In this
+     * case, the server is free to pick any group it likes. See RFC 4492,
      * section 4, paragraph 3.
      *
      * However, in the interests of compatibility, we will skip ECDH if the
      * client didn't send an extension because we can't be sure that they'll
-     * support our favoured curve. */
+     * support our favoured group. */
     return 0;
   }
 
   if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
-    pref = curves;
-    pref_len = curves_len;
-    supp = peer_curves;
-    supp_len = peer_curves_len;
+    pref = groups;
+    pref_len = groups_len;
+    supp = peer_groups;
+    supp_len = peer_groups_len;
   } else {
-    pref = peer_curves;
-    pref_len = peer_curves_len;
-    supp = curves;
-    supp_len = curves_len;
+    pref = peer_groups;
+    pref_len = peer_groups_len;
+    supp = groups;
+    supp_len = groups_len;
   }
 
   for (i = 0; i < pref_len; i++) {
     for (j = 0; j < supp_len; j++) {
       if (pref[i] == supp[j]) {
-        *out_curve_id = pref[i];
+        *out_group_id = pref[i];
         return 1;
       }
     }
@@ -370,34 +370,34 @@
   return 0;
 }
 
-int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
+int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len,
                     const int *curves, size_t ncurves) {
-  uint16_t *curve_ids;
+  uint16_t *group_ids;
   size_t i;
 
-  curve_ids = OPENSSL_malloc(ncurves * sizeof(uint16_t));
-  if (curve_ids == NULL) {
+  group_ids = OPENSSL_malloc(ncurves * sizeof(uint16_t));
+  if (group_ids == NULL) {
     return 0;
   }
 
   for (i = 0; i < ncurves; i++) {
-    if (!ssl_nid_to_curve_id(&curve_ids[i], curves[i])) {
-      OPENSSL_free(curve_ids);
+    if (!ssl_nid_to_group_id(&group_ids[i], curves[i])) {
+      OPENSSL_free(group_ids);
       return 0;
     }
   }
 
-  OPENSSL_free(*out_curve_ids);
-  *out_curve_ids = curve_ids;
-  *out_curve_ids_len = ncurves;
+  OPENSSL_free(*out_group_ids);
+  *out_group_ids = group_ids;
+  *out_group_ids_len = ncurves;
 
   return 1;
 }
 
-/* tls1_curve_params_from_ec_key sets |*out_curve_id| and |*out_comp_id| to the
- * TLS curve ID and point format, respectively, for |ec|. It returns one on
+/* tls1_curve_params_from_ec_key sets |*out_group_id| and |*out_comp_id| to the
+ * TLS group ID and point format, respectively, for |ec|. It returns one on
  * success and zero on failure. */
-static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id,
+static int tls1_curve_params_from_ec_key(uint16_t *out_group_id,
                                          uint8_t *out_comp_id, EC_KEY *ec) {
   int nid;
   uint16_t id;
@@ -412,14 +412,14 @@
     return 0;
   }
 
-  /* Determine curve ID */
+  /* Determine group ID */
   nid = EC_GROUP_get_curve_name(grp);
-  if (!ssl_nid_to_curve_id(&id, nid)) {
+  if (!ssl_nid_to_group_id(&id, nid)) {
     return 0;
   }
 
-  /* Set the named curve ID. Arbitrary explicit curves are not supported. */
-  *out_curve_id = id;
+  /* Set the named group ID. Arbitrary explicit groups are not supported. */
+  *out_group_id = id;
 
   if (out_comp_id) {
     if (EC_KEY_get0_public_key(ec) == NULL) {
@@ -435,35 +435,35 @@
   return 1;
 }
 
-/* tls1_check_curve_id returns one if |curve_id| is consistent with both our
- * and the peer's curve preferences. Note: if called as the client, only our
+/* tls1_check_group_id returns one if |group_id| is consistent with both our
+ * and the peer's group preferences. Note: if called as the client, only our
  * preferences are checked; the peer (the server) does not send preferences. */
-int tls1_check_curve_id(SSL *ssl, uint16_t curve_id) {
-  const uint16_t *curves;
-  size_t curves_len, i, get_peer_curves;
+int tls1_check_group_id(SSL *ssl, uint16_t group_id) {
+  const uint16_t *groups;
+  size_t groups_len, i, get_peer_groups;
 
   /* Check against our list, then the peer's list. */
-  for (get_peer_curves = 0; get_peer_curves <= 1; get_peer_curves++) {
-    if (get_peer_curves && !ssl->server) {
+  for (get_peer_groups = 0; get_peer_groups <= 1; get_peer_groups++) {
+    if (get_peer_groups && !ssl->server) {
       /* Servers do not present a preference list so, if we are a client, only
        * check our list. */
       continue;
     }
 
-    tls1_get_curvelist(ssl, get_peer_curves, &curves, &curves_len);
-    if (get_peer_curves && curves_len == 0) {
-      /* Clients are not required to send a supported_curves extension. In this
-       * case, the server is free to pick any curve it likes. See RFC 4492,
+    tls1_get_grouplist(ssl, get_peer_groups, &groups, &groups_len);
+    if (get_peer_groups && groups_len == 0) {
+      /* Clients are not required to send a supported_groups extension. In this
+       * case, the server is free to pick any group it likes. See RFC 4492,
        * section 4, paragraph 3. */
       continue;
     }
-    for (i = 0; i < curves_len; i++) {
-      if (curves[i] == curve_id) {
+    for (i = 0; i < groups_len; i++) {
+      if (groups[i] == group_id) {
         break;
       }
     }
 
-    if (i == curves_len) {
+    if (i == groups_len) {
       return 0;
     }
   }
@@ -474,7 +474,7 @@
 int tls1_check_ec_cert(SSL *ssl, X509 *x) {
   int ret = 0;
   EVP_PKEY *pkey = X509_get_pubkey(x);
-  uint16_t curve_id;
+  uint16_t group_id;
   uint8_t comp_id;
 
   if (!pkey) {
@@ -482,8 +482,8 @@
   }
   EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
   if (ec_key == NULL ||
-      !tls1_curve_params_from_ec_key(&curve_id, &comp_id, ec_key) ||
-      !tls1_check_curve_id(ssl, curve_id) ||
+      !tls1_curve_params_from_ec_key(&group_id, &comp_id, ec_key) ||
+      !tls1_check_group_id(ssl, group_id) ||
       comp_id != TLSEXT_ECPOINTFORMAT_uncompressed) {
     goto done;
   }
@@ -1809,35 +1809,36 @@
 }
 
 
-/* EC supported curves.
+/* Negotiated Groups
  *
- * https://tools.ietf.org/html/rfc4492#section-5.1.2 */
+ * https://tools.ietf.org/html/rfc4492#section-5.1.2
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-12#section-6.3.2.2 */
 
-static void ext_ec_curves_init(SSL *ssl) {
-  OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
-  ssl->s3->tmp.peer_ellipticcurvelist = NULL;
-  ssl->s3->tmp.peer_ellipticcurvelist_length = 0;
+static void ext_supported_groups_init(SSL *ssl) {
+  OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
+  ssl->s3->tmp.peer_supported_group_list = NULL;
+  ssl->s3->tmp.peer_supported_group_list_len = 0;
 }
 
-static int ext_ec_curves_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_supported_groups_add_clienthello(SSL *ssl, CBB *out) {
   if (!ssl_any_ec_cipher_suites_enabled(ssl)) {
     return 1;
   }
 
-  CBB contents, curves_bytes;
-  if (!CBB_add_u16(out, TLSEXT_TYPE_elliptic_curves) ||
+  CBB contents, groups_bytes;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_supported_groups) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_u16_length_prefixed(&contents, &curves_bytes)) {
+      !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) {
     return 0;
   }
 
-  const uint16_t *curves;
-  size_t curves_len;
-  tls1_get_curvelist(ssl, 0, &curves, &curves_len);
+  const uint16_t *groups;
+  size_t groups_len;
+  tls1_get_grouplist(ssl, 0, &groups, &groups_len);
 
   size_t i;
-  for (i = 0; i < curves_len; i++) {
-    if (!CBB_add_u16(&curves_bytes, curves[i])) {
+  for (i = 0; i < groups_len; i++) {
+    if (!CBB_add_u16(&groups_bytes, groups[i])) {
       return 0;
     }
   }
@@ -1845,54 +1846,55 @@
   return CBB_flush(out);
 }
 
-static int ext_ec_curves_parse_serverhello(SSL *ssl, uint8_t *out_alert,
-                                           CBS *contents) {
+static int ext_supported_groups_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+                                                  CBS *contents) {
   /* This extension is not expected to be echoed by servers and is ignored. */
   return 1;
 }
 
-static int ext_ec_curves_parse_clienthello(SSL *ssl, uint8_t *out_alert,
-                                           CBS *contents) {
+static int ext_supported_groups_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+                                                  CBS *contents) {
   if (contents == NULL) {
     return 1;
   }
 
-  CBS elliptic_curve_list;
-  if (!CBS_get_u16_length_prefixed(contents, &elliptic_curve_list) ||
-      CBS_len(&elliptic_curve_list) == 0 ||
-      (CBS_len(&elliptic_curve_list) & 1) != 0 ||
+  CBS supported_group_list;
+  if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) ||
+      CBS_len(&supported_group_list) == 0 ||
+      (CBS_len(&supported_group_list) & 1) != 0 ||
       CBS_len(contents) != 0) {
     return 0;
   }
 
-  ssl->s3->tmp.peer_ellipticcurvelist = OPENSSL_malloc(CBS_len(&elliptic_curve_list));
-  if (ssl->s3->tmp.peer_ellipticcurvelist == NULL) {
+  ssl->s3->tmp.peer_supported_group_list = OPENSSL_malloc(
+      CBS_len(&supported_group_list));
+  if (ssl->s3->tmp.peer_supported_group_list == NULL) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
     return 0;
   }
 
-  const size_t num_curves = CBS_len(&elliptic_curve_list) / 2;
+  const size_t num_groups = CBS_len(&supported_group_list) / 2;
   size_t i;
-  for (i = 0; i < num_curves; i++) {
-    if (!CBS_get_u16(&elliptic_curve_list,
-                     &ssl->s3->tmp.peer_ellipticcurvelist[i])) {
+  for (i = 0; i < num_groups; i++) {
+    if (!CBS_get_u16(&supported_group_list,
+                     &ssl->s3->tmp.peer_supported_group_list[i])) {
       goto err;
     }
   }
 
-  assert(CBS_len(&elliptic_curve_list) == 0);
-  ssl->s3->tmp.peer_ellipticcurvelist_length = num_curves;
+  assert(CBS_len(&supported_group_list) == 0);
+  ssl->s3->tmp.peer_supported_group_list_len = num_groups;
 
   return 1;
 
 err:
-  OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
-  ssl->s3->tmp.peer_ellipticcurvelist = NULL;
+  OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
+  ssl->s3->tmp.peer_supported_group_list = NULL;
   *out_alert = SSL_AD_INTERNAL_ERROR;
   return 0;
 }
 
-static int ext_ec_curves_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_supported_groups_add_serverhello(SSL *ssl, CBB *out) {
   /* Servers don't echo this extension. */
   return 1;
 }
@@ -2003,12 +2005,12 @@
    * intolerant to the last extension being zero-length. See
    * https://crbug.com/363583. */
   {
-    TLSEXT_TYPE_elliptic_curves,
-    ext_ec_curves_init,
-    ext_ec_curves_add_clienthello,
-    ext_ec_curves_parse_serverhello,
-    ext_ec_curves_parse_clienthello,
-    ext_ec_curves_add_serverhello,
+    TLSEXT_TYPE_supported_groups,
+    ext_supported_groups_init,
+    ext_supported_groups_add_clienthello,
+    ext_supported_groups_parse_serverhello,
+    ext_supported_groups_parse_clienthello,
+    ext_supported_groups_add_serverhello,
   },
 };