Skip to content

Commit 2da5ba9

Browse files
davidbenBoringssl LUCI CQ
authored and
Boringssl LUCI CQ
committed
Align on using the "group" over "curve" for ECDH in TLS
We're this awkward mix of "group" and "curve" right now. On the spec side, this is because they used to be "curves", but then RFC 7919 renamed to "group" in an attempt to generalize FFDH and ECDH. The negotiated FFDH stuff never really went anywhere (the way it used cipher suite values in TLS 1.2 made it unusable), but the name change stuck. In our implementation and API, we originally called it "curve". In preparation for TLS 1.3, we renamed the internals to "group" to match the spec in https://boringssl-review.googlesource.com/c/boringssl/+/7955, but the public API was still "curve". Then we exported a few more things in https://boringssl-review.googlesource.com/c/boringssl/+/8565, but I left it at "curve" to keep the public API self-consistent. Then we added OpenSSL's new "group" APIs in https://boringssl-review.googlesource.com/c/boringssl/+/54306, but didn't go as far to deprecate the old ones yet. Now I'd like to add new APIs to clear up the weird mix of TLS codepoints and NIDs that appear in our APIs. But our naming is a mess, so either choice of "group" or "curve" for the new API looks weird. In hindsight, we probably should have left it at "curve". Both terms are equally useless for the future post-quantum KEMs, but at least "curve" is more unique of a name than "group". But at this point, I think we're too far through the "group" rename to really backtrack: - Chromium says "group" in its internals - QUICHE says "group" in its internals and public API - Our internals say "group" - OpenSSL has switched to "group" and deprecated "curve", so new APIs will be based on "group" So align with all this and say "group". This CL handles set1_curves and set1_curves_list APIs, which already have "group" replacements from OpenSSL. A follow-up CL will handle our APIs. This is a soft deprecation because I don't think updating things is particularly worth the churn, but get the old names out of the way, so new code can have a simpler API to target. Also rewrite the documentation for that section accordingly. I don't think we need to talk about how it's always enabled now. That's a reference to some very, very old OpenSSL behavior where ECDH negotiation needed to be separately enabled. Change-Id: I7a356793d36419fc668364c912ca7b4f5c6c23a2 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60206 Commit-Queue: David Benjamin <[email protected]> Reviewed-by: Adam Langley <[email protected]> Reviewed-by: Bob Beck <[email protected]>
1 parent 4631ccc commit 2da5ba9

File tree

7 files changed

+137
-160
lines changed

7 files changed

+137
-160
lines changed

fuzz/ssl_ctx_api.cc

+6-6
Original file line numberDiff line numberDiff line change
@@ -410,18 +410,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
410410
SSL_CTX_set_tlsext_ticket_keys(ctx, keys.data(), keys.size());
411411
},
412412
[](SSL_CTX *ctx, CBS *cbs) {
413-
std::vector<int> curves;
414-
if (!GetVector(&curves, cbs)) {
413+
std::vector<int> groups;
414+
if (!GetVector(&groups, cbs)) {
415415
return;
416416
}
417-
SSL_CTX_set1_curves(ctx, curves.data(), curves.size());
417+
SSL_CTX_set1_groups(ctx, groups.data(), groups.size());
418418
},
419419
[](SSL_CTX *ctx, CBS *cbs) {
420-
std::string curves;
421-
if (!GetString(&curves, cbs)) {
420+
std::string groups;
421+
if (!GetString(&groups, cbs)) {
422422
return;
423423
}
424-
SSL_CTX_set1_curves_list(ctx, curves.c_str());
424+
SSL_CTX_set1_groups_list(ctx, groups.c_str());
425425
},
426426
[](SSL_CTX *ctx, CBS *cbs) {
427427
SSL_CTX_enable_signed_cert_timestamps(ctx);

include/openssl/ssl.h

+52-50
Original file line numberDiff line numberDiff line change
@@ -2331,45 +2331,51 @@ OPENSSL_EXPORT int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
23312331
OPENSSL_EXPORT size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);
23322332

23332333

2334-
// Elliptic curve Diffie-Hellman.
2335-
//
2336-
// Cipher suites using an ECDHE key exchange perform Diffie-Hellman over an
2337-
// elliptic curve negotiated by both endpoints. See RFC 4492. Only named curves
2338-
// are supported. ECDHE is always enabled, but the curve preferences may be
2339-
// configured with these functions.
2340-
//
2341-
// Note that TLS 1.3 renames these from curves to groups. For consistency, we
2342-
// currently use the TLS 1.2 name in the API.
2343-
2344-
// SSL_CTX_set1_curves sets the preferred curves for |ctx| to be |curves|. Each
2345-
// element of |curves| should be a curve nid. It returns one on success and
2346-
// zero on failure.
2334+
// Diffie-Hellman groups and ephemeral key exchanges.
2335+
//
2336+
// Most TLS handshakes (ECDHE cipher suites in TLS 1.2, and all supported TLS
2337+
// 1.3 modes) incorporate an ephemeral key exchange, most commonly using
2338+
// Elliptic Curve Diffie-Hellman (ECDH), as described in RFC 8422. The key
2339+
// exchange algorithm is negotiated separately from the cipher suite, using
2340+
// NamedGroup values, which define Diffie-Hellman groups.
2341+
//
2342+
// Historically, these values were known as "curves", in reference to ECDH, and
2343+
// some APIs refer to the original name. RFC 7919 renamed them to "groups" in
2344+
// reference to Diffie-Hellman in general. These values are also used to select
2345+
// experimental post-quantum KEMs. Though not Diffie-Hellman groups, KEMs can
2346+
// fill a similar role in TLS, so they use the same codepoints.
2347+
//
2348+
// In TLS 1.2, the ECDH values also negotiate elliptic curves used in ECDSA. In
2349+
// TLS 1.3 and later, ECDSA curves are part of the signature algorithm. See
2350+
// |SSL_SIGN_*|.
2351+
2352+
// SSL_CTX_set1_groups sets the preferred groups for |ctx| to be |groups|. Each
2353+
// element of |groups| should be a |NID_*| constant from nid.h. It returns one
2354+
// on success and zero on failure.
23472355
//
2348-
// Note that this API uses nid values from nid.h and not the |SSL_CURVE_*|
2349-
// values defined below.
2350-
OPENSSL_EXPORT int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves,
2351-
size_t curves_len);
2356+
// Note that this API does not use the |SSL_CURVE_*| values defined below.
2357+
OPENSSL_EXPORT int SSL_CTX_set1_groups(SSL_CTX *ctx, const int *groups,
2358+
size_t num_groups);
23522359

2353-
// SSL_set1_curves sets the preferred curves for |ssl| to be |curves|. Each
2354-
// element of |curves| should be a curve nid. It returns one on success and
2355-
// zero on failure.
2360+
// SSL_set1_groups sets the preferred groups for |ssl| to be |groups|. Each
2361+
// element of |groups| should be a |NID_*| constant from nid.h. It returns one
2362+
// on success and zero on failure.
23562363
//
2357-
// Note that this API uses nid values from nid.h and not the |SSL_CURVE_*|
2358-
// values defined below.
2359-
OPENSSL_EXPORT int SSL_set1_curves(SSL *ssl, const int *curves,
2360-
size_t curves_len);
2364+
// Note that this API does not use the |SSL_CURVE_*| values defined below.
2365+
OPENSSL_EXPORT int SSL_set1_groups(SSL *ssl, const int *groups,
2366+
size_t num_groups);
23612367

2362-
// SSL_CTX_set1_curves_list sets the preferred curves for |ctx| to be the
2363-
// colon-separated list |curves|. Each element of |curves| should be a curve
2368+
// SSL_CTX_set1_groups_list sets the preferred groups for |ctx| to be the
2369+
// colon-separated list |groups|. Each element of |groups| should be a curve
23642370
// name (e.g. P-256, X25519, ...). It returns one on success and zero on
23652371
// failure.
2366-
OPENSSL_EXPORT int SSL_CTX_set1_curves_list(SSL_CTX *ctx, const char *curves);
2372+
OPENSSL_EXPORT int SSL_CTX_set1_groups_list(SSL_CTX *ctx, const char *groups);
23672373

2368-
// SSL_set1_curves_list sets the preferred curves for |ssl| to be the
2369-
// colon-separated list |curves|. Each element of |curves| should be a curve
2374+
// SSL_set1_groups_list sets the preferred groups for |ssl| to be the
2375+
// colon-separated list |groups|. Each element of |groups| should be a curve
23702376
// name (e.g. P-256, X25519, ...). It returns one on success and zero on
23712377
// failure.
2372-
OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
2378+
OPENSSL_EXPORT int SSL_set1_groups_list(SSL *ssl, const char *groups);
23732379

23742380
// SSL_CURVE_* define TLS curve IDs.
23752381
#define SSL_CURVE_SECP224R1 21
@@ -2404,20 +2410,6 @@ OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t curve_id);
24042410
// list, so this does not apply if, say, sending strings across services.
24052411
OPENSSL_EXPORT size_t SSL_get_all_curve_names(const char **out, size_t max_out);
24062412

2407-
// SSL_CTX_set1_groups calls |SSL_CTX_set1_curves|.
2408-
OPENSSL_EXPORT int SSL_CTX_set1_groups(SSL_CTX *ctx, const int *groups,
2409-
size_t groups_len);
2410-
2411-
// SSL_set1_groups calls |SSL_set1_curves|.
2412-
OPENSSL_EXPORT int SSL_set1_groups(SSL *ssl, const int *groups,
2413-
size_t groups_len);
2414-
2415-
// SSL_CTX_set1_groups_list calls |SSL_CTX_set1_curves_list|.
2416-
OPENSSL_EXPORT int SSL_CTX_set1_groups_list(SSL_CTX *ctx, const char *groups);
2417-
2418-
// SSL_set1_groups_list calls |SSL_set1_curves_list|.
2419-
OPENSSL_EXPORT int SSL_set1_groups_list(SSL *ssl, const char *groups);
2420-
24212413

24222414
// Certificate verification.
24232415
//
@@ -5090,12 +5082,12 @@ OPENSSL_EXPORT int SSL_state(const SSL *ssl);
50905082
// Use |SSL_CTX_set_quiet_shutdown| instead.
50915083
OPENSSL_EXPORT void SSL_set_shutdown(SSL *ssl, int mode);
50925084

5093-
// SSL_CTX_set_tmp_ecdh calls |SSL_CTX_set1_curves| with a one-element list
5094-
// containing |ec_key|'s curve.
5085+
// SSL_CTX_set_tmp_ecdh calls |SSL_CTX_set1_groups| with a one-element list
5086+
// containing |ec_key|'s curve. The remainder of |ec_key| is ignored.
50955087
OPENSSL_EXPORT int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key);
50965088

5097-
// SSL_set_tmp_ecdh calls |SSL_set1_curves| with a one-element list containing
5098-
// |ec_key|'s curve.
5089+
// SSL_set_tmp_ecdh calls |SSL_set1_groups| with a one-element list containing
5090+
// |ec_key|'s curve. The remainder of |ec_key| is ignored.
50995091
OPENSSL_EXPORT int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key);
51005092

51015093
// SSL_add_dir_cert_subjects_to_stack lists files in directory |dir|. It calls
@@ -5244,6 +5236,14 @@ OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
52445236
SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_HASH_VALUE
52455237
#define SSL_R_TLSV1_CERTIFICATE_REQUIRED SSL_R_TLSV1_ALERT_CERTIFICATE_REQUIRED
52465238

5239+
// The following symbols are compatibility aliases for equivalent functions that
5240+
// use the newer "group" terminology. New code should use the new functions for
5241+
// consistency, but we do not plan to remove these aliases.
5242+
#define SSL_CTX_set1_curves SSL_CTX_set1_groups
5243+
#define SSL_set1_curves SSL_set1_groups
5244+
#define SSL_CTX_set1_curves_list SSL_CTX_set1_groups_list
5245+
#define SSL_set1_curves_list SSL_set1_groups_list
5246+
52475247

52485248
// Compliance policy configurations
52495249
//
@@ -5359,6 +5359,8 @@ OPENSSL_EXPORT int SSL_set_compliance_policy(
53595359
#define SSL_CTRL_SESS_NUMBER doesnt_exist
53605360
#define SSL_CTRL_SET_CURVES doesnt_exist
53615361
#define SSL_CTRL_SET_CURVES_LIST doesnt_exist
5362+
#define SSL_CTRL_SET_GROUPS doesnt_exist
5363+
#define SSL_CTRL_SET_GROUPS_LIST doesnt_exist
53625364
#define SSL_CTRL_SET_ECDH_AUTO doesnt_exist
53635365
#define SSL_CTRL_SET_MAX_CERT_LIST doesnt_exist
53645366
#define SSL_CTRL_SET_MAX_SEND_FRAGMENT doesnt_exist
@@ -5407,7 +5409,7 @@ OPENSSL_EXPORT int SSL_set_compliance_policy(
54075409
#define SSL_CTX_sess_set_cache_size SSL_CTX_sess_set_cache_size
54085410
#define SSL_CTX_set0_chain SSL_CTX_set0_chain
54095411
#define SSL_CTX_set1_chain SSL_CTX_set1_chain
5410-
#define SSL_CTX_set1_curves SSL_CTX_set1_curves
5412+
#define SSL_CTX_set1_groups SSL_CTX_set1_groups
54115413
#define SSL_CTX_set_max_cert_list SSL_CTX_set_max_cert_list
54125414
#define SSL_CTX_set_max_send_fragment SSL_CTX_set_max_send_fragment
54135415
#define SSL_CTX_set_mode SSL_CTX_set_mode
@@ -5440,7 +5442,7 @@ OPENSSL_EXPORT int SSL_set_compliance_policy(
54405442
#define SSL_session_reused SSL_session_reused
54415443
#define SSL_set0_chain SSL_set0_chain
54425444
#define SSL_set1_chain SSL_set1_chain
5443-
#define SSL_set1_curves SSL_set1_curves
5445+
#define SSL_set1_groups SSL_set1_groups
54445446
#define SSL_set_max_cert_list SSL_set_max_cert_list
54455447
#define SSL_set_max_send_fragment SSL_set_max_send_fragment
54465448
#define SSL_set_mode SSL_set_mode

ssl/extensions.cc

-51
Original file line numberDiff line numberDiff line change
@@ -358,57 +358,6 @@ bool tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
358358
return false;
359359
}
360360

361-
bool tls1_set_curves(Array<uint16_t> *out_group_ids, Span<const int> curves) {
362-
Array<uint16_t> group_ids;
363-
if (!group_ids.Init(curves.size())) {
364-
return false;
365-
}
366-
367-
for (size_t i = 0; i < curves.size(); i++) {
368-
if (!ssl_nid_to_group_id(&group_ids[i], curves[i])) {
369-
return false;
370-
}
371-
}
372-
373-
*out_group_ids = std::move(group_ids);
374-
return true;
375-
}
376-
377-
bool tls1_set_curves_list(Array<uint16_t> *out_group_ids, const char *curves) {
378-
// Count the number of curves in the list.
379-
size_t count = 0;
380-
const char *ptr = curves, *col;
381-
do {
382-
col = strchr(ptr, ':');
383-
count++;
384-
if (col) {
385-
ptr = col + 1;
386-
}
387-
} while (col);
388-
389-
Array<uint16_t> group_ids;
390-
if (!group_ids.Init(count)) {
391-
return false;
392-
}
393-
394-
size_t i = 0;
395-
ptr = curves;
396-
do {
397-
col = strchr(ptr, ':');
398-
if (!ssl_name_to_group_id(&group_ids[i++], ptr,
399-
col ? (size_t)(col - ptr) : strlen(ptr))) {
400-
return false;
401-
}
402-
if (col) {
403-
ptr = col + 1;
404-
}
405-
} while (col);
406-
407-
assert(i == count);
408-
*out_group_ids = std::move(group_ids);
409-
return true;
410-
}
411-
412361
bool tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
413362
if (is_post_quantum_group(group_id) &&
414363
ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {

ssl/internal.h

-11
Original file line numberDiff line numberDiff line change
@@ -3353,17 +3353,6 @@ bool tls1_check_group_id(const SSL_HANDSHAKE *ssl, uint16_t group_id);
33533353
// found, it returns false.
33543354
bool tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id);
33553355

3356-
// tls1_set_curves converts the array of NIDs in |curves| into a newly allocated
3357-
// array of TLS group IDs. On success, the function returns true and writes the
3358-
// array to |*out_group_ids|. Otherwise, it returns false.
3359-
bool tls1_set_curves(Array<uint16_t> *out_group_ids, Span<const int> curves);
3360-
3361-
// tls1_set_curves_list converts the string of curves pointed to by |curves|
3362-
// into a newly allocated array of TLS group IDs. On success, the function
3363-
// returns true and writes the array to |*out_group_ids|. Otherwise, it returns
3364-
// false.
3365-
bool tls1_set_curves_list(Array<uint16_t> *out_group_ids, const char *curves);
3366-
33673356
// ssl_add_clienthello_tlsext writes ClientHello extensions to |out| for |type|.
33683357
// It returns true on success and false on failure. The |header_len| argument is
33693358
// the length of the ClientHello written so far and is used to compute the

0 commit comments

Comments
 (0)