Skip to content

Commit

Permalink
Turning on support for Curve x25519 w/ ECC curve configurations (aws#…
Browse files Browse the repository at this point in the history
…1693)

* Allowing different ECC curve configurations and turning on support for Curve x25519

* Addressing PR comments

* Addressing PR comments #2

* Addressing PR comments #3
  • Loading branch information
ttjsu-aws authored Mar 27, 2020
1 parent a9d4d87 commit f3abfab
Show file tree
Hide file tree
Showing 46 changed files with 971 additions and 346 deletions.
1 change: 1 addition & 0 deletions api/s2n.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ extern int s2n_config_set_max_cert_chain_depth(struct s2n_config *config, uint16
extern int s2n_config_add_dhparams(struct s2n_config *config, const char *dhparams_pem);
extern int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *version);
extern int s2n_config_set_signature_preferences(struct s2n_config *config, const char *version);
extern int s2n_config_set_ecc_preferences(struct s2n_config *config, const char *version);
extern int s2n_config_set_protocol_preferences(struct s2n_config *config, const char * const *protocols, int protocol_count);
typedef enum { S2N_STATUS_REQUEST_NONE = 0, S2N_STATUS_REQUEST_OCSP = 1 } s2n_status_request_type;
extern int s2n_config_set_status_request_type(struct s2n_config *config, s2n_status_request_type type);
Expand Down
16 changes: 13 additions & 3 deletions bin/s2nc.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ void usage()
fprintf(stderr, " -c [version_string]\n");
fprintf(stderr, " --ciphers [version_string]\n");
fprintf(stderr, " Set the cipher preference version string. Defaults to \"default\". See USAGE-GUIDE.md\n");
fprintf(stderr, " -u [version_string]\n");
fprintf(stderr, " --curves [version_string]\n");
fprintf(stderr, " Set the ecc preference version string. Defaults to \"default\". See USAGE-GUIDE.md\n");
fprintf(stderr, " -e\n");
fprintf(stderr, " --echo\n");
fprintf(stderr, " Listen to stdin after TLS Connection is established and echo it to the Server\n");
Expand Down Expand Up @@ -105,7 +108,7 @@ extern void print_s2n_error(const char *app_error);
extern int echo(struct s2n_connection *conn, int sockfd);
extern int negotiate(struct s2n_connection *conn);

static void setup_s2n_config(struct s2n_config *config, const char *cipher_prefs, s2n_status_request_type type,
static void setup_s2n_config(struct s2n_config *config, const char *cipher_prefs, const char *ecc_prefs, s2n_status_request_type type,
struct verify_data *unsafe_verify_data, const char *host, const char *alpn_protocols, uint16_t mfl_value) {

if (config == NULL) {
Expand All @@ -115,6 +118,8 @@ static void setup_s2n_config(struct s2n_config *config, const char *cipher_prefs

GUARD_EXIT(s2n_config_set_cipher_preferences(config, cipher_prefs), "Error setting cipher prefs");

GUARD_EXIT(s2n_config_set_ecc_preferences(config, ecc_prefs), "Error setting ecc prefs");

GUARD_EXIT(s2n_config_set_status_request_type(config, type), "OCSP validation is not supported by the linked libCrypto implementation. It cannot be set.");

if (s2n_config_set_verify_host_callback(config, unsafe_verify_host, unsafe_verify_data) < 0) {
Expand Down Expand Up @@ -232,6 +237,7 @@ int main(int argc, char *const *argv)
uint8_t dyn_rec_timeout = 0;
/* required args */
const char *cipher_prefs = "default";
const char *ecc_prefs = "default";
const char *host = NULL;
struct verify_data unsafe_verify_data;
const char *port = "443";
Expand All @@ -256,11 +262,12 @@ int main(int argc, char *const *argv)
{"timeout", required_argument, 0, 't'},
{"corked-io", no_argument, 0, 'C'},
{"tls13", no_argument, 0, '3'},
{"curves", required_argument, NULL, 'u'},
};

while (1) {
int option_index = 0;
int c = getopt_long(argc, argv, "a:c:ehn:sf:d:D:t:irTC", long_options, &option_index);
int c = getopt_long(argc, argv, "a:c:ehn:sf:d:D:t:irTCu:", long_options, &option_index);
if (c == -1) {
break;
}
Expand Down Expand Up @@ -317,6 +324,9 @@ int main(int argc, char *const *argv)
case '3':
use_tls13 = 1;
break;
case 'u':
ecc_prefs = optarg;
break;
case '?':
default:
usage();
Expand Down Expand Up @@ -381,7 +391,7 @@ int main(int argc, char *const *argv)
}

struct s2n_config *config = s2n_config_new();
setup_s2n_config(config, cipher_prefs, type, &unsafe_verify_data, host, alpn_protocols, mfl_value);
setup_s2n_config(config, cipher_prefs, ecc_prefs, type, &unsafe_verify_data, host, alpn_protocols, mfl_value);

if (ca_file || ca_dir) {
if (s2n_config_set_verification_ca_location(config, ca_file, ca_dir) < 0) {
Expand Down
12 changes: 11 additions & 1 deletion bin/s2nd.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ void usage()
fprintf(stderr, " -c [version_string]\n");
fprintf(stderr, " --ciphers [version_string]\n");
fprintf(stderr, " Set the cipher preference version string. Defaults to \"default\". See USAGE-GUIDE.md\n");
fprintf(stderr, " -u [version_string]\n");
fprintf(stderr, " --curves [version_string]\n");
fprintf(stderr, " Set the ecc preference version string. Defaults to \"default\". See USAGE-GUIDE.md\n");
fprintf(stderr, " --enter-fips-mode\n");
fprintf(stderr, " Enter libcrypto's FIPS mode. The linked version of OpenSSL must be built with the FIPS module.\n");
fprintf(stderr, " --cert\n");
Expand Down Expand Up @@ -431,6 +434,7 @@ int main(int argc, char *const *argv)
const char *ocsp_response_file_path = NULL;
const char *session_ticket_key_file_path = NULL;
const char *cipher_prefs = "default";
const char *ecc_prefs = "default";

/* The certificates provided by the user. If there are none provided, we will use the hardcoded default cert.
* The associated private key for each cert will be at the same index in private_keys. If the user mixes up the
Expand Down Expand Up @@ -469,12 +473,13 @@ int main(int argc, char *const *argv)
{"no-session-ticket", no_argument, 0, 'T'},
{"corked-io", no_argument, 0, 'C'},
{"tls13", no_argument, 0, '3'},
{"curves", required_argument, NULL, 'u'},
/* Per getopt(3) the last element of the array has to be filled with all zeros */
{ 0 },
};
while (1) {
int option_index = 0;
int c = getopt_long(argc, argv, "c:hmnst:d:iTC", long_options, &option_index);
int c = getopt_long(argc, argv, "c:hmnst:d:iTCu:", long_options, &option_index);
if (c == -1) {
break;
}
Expand Down Expand Up @@ -550,6 +555,9 @@ int main(int argc, char *const *argv)
case '3':
use_tls13 = 1;
break;
case 'u':
ecc_prefs = optarg;
break;
case '?':
default:
fprintf(stdout, "getopt_long returned: %d", c);
Expand Down Expand Up @@ -698,6 +706,8 @@ int main(int argc, char *const *argv)

GUARD_EXIT(s2n_config_set_cipher_preferences(config, cipher_prefs),"Error setting cipher prefs");

GUARD_EXIT(s2n_config_set_ecc_preferences(config, ecc_prefs), "Error setting ecc prefs");

GUARD_EXIT(s2n_config_set_cache_store_callback(config, cache_store_callback, session_cache), "Error setting cache store callback");

GUARD_EXIT(s2n_config_set_cache_retrieve_callback(config, cache_retrieve_callback, session_cache), "Error setting cache retrieve callback");
Expand Down
69 changes: 45 additions & 24 deletions crypto/s2n_ecc_evp.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ DEFINE_POINTER_CLEANUP_FUNC(EVP_PKEY *, EVP_PKEY_free);
DEFINE_POINTER_CLEANUP_FUNC(EVP_PKEY_CTX *, EVP_PKEY_CTX_free);
DEFINE_POINTER_CLEANUP_FUNC(EC_KEY *, EC_KEY_free);

#if !MODERN_EC_SUPPORTED
#if !EVP_APIS_SUPPORTED
DEFINE_POINTER_CLEANUP_FUNC(EC_POINT *, EC_POINT_free);
#endif

Expand All @@ -53,23 +53,37 @@ const struct s2n_ecc_named_curve s2n_ecc_curve_secp384r1 =
.share_size = ( 48 * 2 ) + 1
};

#if MODERN_EC_SUPPORTED
#if EVP_APIS_SUPPORTED
const struct s2n_ecc_named_curve s2n_ecc_curve_x25519 = {
.iana_id = TLS_EC_CURVE_ECDH_X25519,
.libcrypto_nid = NID_X25519,
.name = "x25519",
.share_size = 32
};
#else
const struct s2n_ecc_named_curve s2n_ecc_curve_x25519 = {0};
#endif

const struct s2n_ecc_named_curve *const s2n_ecc_evp_supported_curves_list[] = {
/* All curves that s2n supports. New curves MUST be added here.
* This list is a super set of all the curves present in s2n_ecc_preferences list.
*/
const struct s2n_ecc_named_curve *const s2n_all_supported_curves_list[] = {
&s2n_ecc_curve_secp256r1,
&s2n_ecc_curve_secp384r1,
#if EVP_APIS_SUPPORTED
&s2n_ecc_curve_x25519,
#endif
};

const size_t s2n_ecc_evp_supported_curves_list_len = s2n_array_len(s2n_ecc_evp_supported_curves_list);
const size_t s2n_all_supported_curves_list_len = s2n_array_len(s2n_all_supported_curves_list);


int s2n_is_evp_apis_supported()
{
return EVP_APIS_SUPPORTED;
}

#if MODERN_EC_SUPPORTED
#if EVP_APIS_SUPPORTED
static int s2n_ecc_evp_generate_key_x25519(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey);
#else
static int s2n_ecc_evp_write_point_data_snug(const EC_POINT *point, const EC_GROUP *group, struct s2n_blob *out);
Expand All @@ -78,9 +92,9 @@ static EC_POINT *s2n_ecc_evp_blob_to_point(struct s2n_blob *blob, const EC_KEY *
#endif
static int s2n_ecc_evp_generate_key_nist_curves(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey);
static int s2n_ecc_evp_generate_own_key(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey);
static int s2n_ecc_evp_compute_shared_secret(EVP_PKEY *own_key, EVP_PKEY *peer_public, struct s2n_blob *shared_secret);
static int s2n_ecc_evp_compute_shared_secret(EVP_PKEY *own_key, EVP_PKEY *peer_public, uint16_t iana_id, struct s2n_blob *shared_secret);

#if MODERN_EC_SUPPORTED
#if EVP_APIS_SUPPORTED
static int s2n_ecc_evp_generate_key_x25519(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey) {

DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(named_curve->libcrypto_nid, NULL),
Expand Down Expand Up @@ -118,7 +132,7 @@ static int s2n_ecc_evp_generate_key_nist_curves(const struct s2n_ecc_named_curve
}

static int s2n_ecc_evp_generate_own_key(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey) {
#if MODERN_EC_SUPPORTED
#if EVP_APIS_SUPPORTED
if (named_curve->libcrypto_nid == NID_X25519) {
return s2n_ecc_evp_generate_key_x25519(named_curve, evp_pkey);
}
Expand All @@ -129,14 +143,19 @@ static int s2n_ecc_evp_generate_own_key(const struct s2n_ecc_named_curve *named_
S2N_ERROR(S2N_ERR_ECDHE_GEN_KEY);
}

static int s2n_ecc_evp_compute_shared_secret(EVP_PKEY *own_key, EVP_PKEY *peer_public, struct s2n_blob *shared_secret) {
static int s2n_ecc_evp_compute_shared_secret(EVP_PKEY *own_key, EVP_PKEY *peer_public, uint16_t iana_id, struct s2n_blob *shared_secret) {
notnull_check(peer_public);
notnull_check(own_key);

/* Peers MUST validate each other’s public key */
DEFER_CLEANUP(EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(peer_public), EC_KEY_free_pointer);
S2N_ERROR_IF(ec_key == NULL, S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
GUARD_OSSL(EC_KEY_check_key(ec_key), S2N_ERR_ECDHE_SHARED_SECRET);
/* From RFC 8446 Section 4.2.8.2: For the curves secp256r1 and secp384r1 peers MUST validate each other's
* public value Q by ensuring that the point is a valid point on the elliptic curve.
* For the curve x25519 the peer public-key validation check doesn't apply.
*/
if (iana_id == TLS_EC_CURVE_SECP_256_R1 || iana_id == TLS_EC_CURVE_SECP_384_R1) {
DEFER_CLEANUP(EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(peer_public), EC_KEY_free_pointer);
S2N_ERROR_IF(ec_key == NULL, S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
GUARD_OSSL(EC_KEY_check_key(ec_key), S2N_ERR_ECDHE_SHARED_SECRET);
}

size_t shared_secret_size;

Expand Down Expand Up @@ -175,7 +194,7 @@ int s2n_ecc_evp_compute_shared_secret_from_params(struct s2n_ecc_evp_params *pri
S2N_ERROR_IF(private_ecc_evp_params->negotiated_curve->iana_id != public_ecc_evp_params->negotiated_curve->iana_id,
S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
GUARD(s2n_ecc_evp_compute_shared_secret(private_ecc_evp_params->evp_pkey, public_ecc_evp_params->evp_pkey,
shared_key));
private_ecc_evp_params->negotiated_curve->iana_id, shared_key));
return 0;
}

Expand All @@ -195,15 +214,15 @@ int s2n_ecc_evp_compute_shared_secret_as_server(struct s2n_ecc_evp_params *ecc_e
client_public_blob.data = s2n_stuffer_raw_read(Yc_in, client_public_blob.size);
notnull_check(client_public_blob.data);

#if MODERN_EC_SUPPORTED
#if EVP_APIS_SUPPORTED
if (ecc_evp_params->negotiated_curve->libcrypto_nid == NID_X25519) {
GUARD(EVP_PKEY_set_type(peer_key, ecc_evp_params->negotiated_curve->libcrypto_nid));
} else {
DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free_pointer);
S2N_ERROR_IF(pctx == NULL, S2N_ERR_ECDHE_SERIALIZING);
GUARD_OSSL(EVP_PKEY_paramgen_init(pctx), S2N_ERR_ECDHE_SERIALIZING);
GUARD_OSSL(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ecc_evp_params->negotiated_curve->libcrypto_nid), S2N_ERR_ECDHE_SERIALIZING);
GUARD(EVP_PKEY_paramgen(pctx, &peer_key));
GUARD_OSSL(EVP_PKEY_paramgen(pctx, &peer_key), S2N_ERR_ECDHE_SERIALIZING);
}
GUARD_OSSL(EVP_PKEY_set1_tls_encodedpoint(peer_key, client_public_blob.data, client_public_blob.size),
S2N_ERR_ECDHE_SERIALIZING);
Expand All @@ -220,7 +239,8 @@ int s2n_ecc_evp_compute_shared_secret_as_server(struct s2n_ecc_evp_params *ecc_e
S2N_ERROR_IF(success == 0, S2N_ERR_BAD_MESSAGE);
#endif

return s2n_ecc_evp_compute_shared_secret(ecc_evp_params->evp_pkey, peer_key, shared_key);
return s2n_ecc_evp_compute_shared_secret(ecc_evp_params->evp_pkey, peer_key,
ecc_evp_params->negotiated_curve->iana_id, shared_key);

}

Expand All @@ -234,7 +254,8 @@ int s2n_ecc_evp_compute_shared_secret_as_client(struct s2n_ecc_evp_params *ecc_e
GUARD(s2n_ecc_evp_generate_own_key(client_params.negotiated_curve, &client_params.evp_pkey));
S2N_ERROR_IF(client_params.evp_pkey == NULL, S2N_ERR_ECDHE_GEN_KEY);

if (s2n_ecc_evp_compute_shared_secret(client_params.evp_pkey, ecc_evp_params->evp_pkey, shared_key) != 0) {
if (s2n_ecc_evp_compute_shared_secret(client_params.evp_pkey, ecc_evp_params->evp_pkey,
ecc_evp_params->negotiated_curve->iana_id, shared_key) != S2N_SUCCESS) {
S2N_ERROR(S2N_ERR_ECDHE_SHARED_SECRET);
}

Expand All @@ -247,7 +268,7 @@ int s2n_ecc_evp_compute_shared_secret_as_client(struct s2n_ecc_evp_params *ecc_e

}

#if (!MODERN_EC_SUPPORTED)
#if (!EVP_APIS_SUPPORTED)
static int s2n_ecc_evp_calculate_point_length(const EC_POINT *point, const EC_GROUP *group, uint8_t *length) {
size_t ret = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
S2N_ERROR_IF(ret == 0, S2N_ERR_ECDHE_SERIALIZING);
Expand Down Expand Up @@ -323,7 +344,7 @@ int s2n_ecc_evp_write_params_point(struct s2n_ecc_evp_params *ecc_evp_params, st
notnull_check(ecc_evp_params->evp_pkey);
notnull_check(out);

#if MODERN_EC_SUPPORTED
#if EVP_APIS_SUPPORTED
struct s2n_blob point_blob = {0};
uint8_t *encoded_point = NULL;

Expand Down Expand Up @@ -390,7 +411,7 @@ int s2n_ecc_evp_parse_params_point(struct s2n_blob *point_blob, struct s2n_ecc_e
notnull_check(ecc_evp_params->negotiated_curve);
S2N_ERROR_IF(point_blob->size != ecc_evp_params->negotiated_curve->share_size, S2N_ERR_ECDHE_SERIALIZING);

#if MODERN_EC_SUPPORTED
#if EVP_APIS_SUPPORTED
if (ecc_evp_params->negotiated_curve->libcrypto_nid == NID_X25519) {
if (ecc_evp_params->evp_pkey == NULL) {
ecc_evp_params->evp_pkey = EVP_PKEY_new();
Expand All @@ -403,7 +424,7 @@ int s2n_ecc_evp_parse_params_point(struct s2n_blob *point_blob, struct s2n_ecc_e
S2N_ERROR_IF(pctx == NULL, S2N_ERR_ECDHE_SERIALIZING);
GUARD_OSSL(EVP_PKEY_paramgen_init(pctx), S2N_ERR_ECDHE_SERIALIZING);
GUARD_OSSL(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ecc_evp_params->negotiated_curve->libcrypto_nid), S2N_ERR_ECDHE_SERIALIZING);
GUARD(EVP_PKEY_paramgen(pctx, &ecc_evp_params->evp_pkey));
GUARD_OSSL(EVP_PKEY_paramgen(pctx, &ecc_evp_params->evp_pkey), S2N_ERR_ECDHE_SERIALIZING);
}
GUARD_OSSL(EVP_PKEY_set1_tls_encodedpoint(ecc_evp_params->evp_pkey, point_blob->data, point_blob->size),
S2N_ERR_ECDHE_SERIALIZING);
Expand Down Expand Up @@ -446,8 +467,8 @@ int s2n_ecc_evp_find_supported_curve(struct s2n_blob *iana_ids, const struct s2n

GUARD(s2n_stuffer_init(&iana_ids_in, iana_ids));
GUARD(s2n_stuffer_write(&iana_ids_in, iana_ids));
for (int i = 0; i < s2n_ecc_evp_supported_curves_list_len; i++) {
const struct s2n_ecc_named_curve *supported_curve = s2n_ecc_evp_supported_curves_list[i];
for (int i = 0; i < s2n_all_supported_curves_list_len; i++) {
const struct s2n_ecc_named_curve *supported_curve = s2n_all_supported_curves_list[i];
for (int j = 0; j < iana_ids->size / 2; j++) {
uint16_t iana_id;
GUARD(s2n_stuffer_read_uint16(&iana_ids_in, &iana_id));
Expand Down
15 changes: 8 additions & 7 deletions crypto/s2n_ecc_evp.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,21 @@ struct s2n_ecc_named_curve {

extern const struct s2n_ecc_named_curve s2n_ecc_curve_secp256r1;
extern const struct s2n_ecc_named_curve s2n_ecc_curve_secp384r1;

#define S2N_ECC_EVP_SUPPORTED_CURVES_COUNT 2
extern const struct s2n_ecc_named_curve s2n_ecc_curve_x25519;

/* BoringSSL only supports using EVP_PKEY_X25519 with "modern" EC EVP APIs. BoringSSL has a note to possibly add this in
* the future. See https://github.com/google/boringssl/blob/master/crypto/evp/p_x25519_asn1.c#L233
*/
#if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0) && !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
#define MODERN_EC_SUPPORTED 1
extern const struct s2n_ecc_named_curve s2n_ecc_curve_x25519;
#define EVP_APIS_SUPPORTED 1
#define S2N_ECC_EVP_SUPPORTED_CURVES_COUNT 3
#else
#define MODERN_EC_SUPPORTED 0
#define EVP_APIS_SUPPORTED 0
#define S2N_ECC_EVP_SUPPORTED_CURVES_COUNT 2
#endif

extern const struct s2n_ecc_named_curve *const s2n_ecc_evp_supported_curves_list[];
extern const size_t s2n_ecc_evp_supported_curves_list_len;
extern const struct s2n_ecc_named_curve *const s2n_all_supported_curves_list[];
extern const size_t s2n_all_supported_curves_list_len;

struct s2n_ecc_evp_params {
const struct s2n_ecc_named_curve *negotiated_curve;
Expand Down Expand Up @@ -77,3 +77,4 @@ int s2n_ecc_evp_parse_params(struct s2n_ecdhe_raw_server_params *raw_server_ecc_
struct s2n_ecc_evp_params *ecc_evp_params);
int s2n_ecc_evp_find_supported_curve(struct s2n_blob *iana_ids, const struct s2n_ecc_named_curve **found);
int s2n_ecc_evp_params_free(struct s2n_ecc_evp_params *ecc_evp_params);
int s2n_is_evp_apis_supported();
19 changes: 18 additions & 1 deletion docs/USAGE-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -544,14 +544,31 @@ int s2n_config_set_signature_preferences(struct s2n_config *config,
**s2n_config_set_signature_preferences** sets the list of acceptable signature schemes (signature + hash algorithms).
The "default" version behaves as in **s2n_config_set_signature_preferences**. Numbered versions are fixed and will never change. The currently supported versions are:
The "default" version behaves as in **s2n_config_set_cipher_preferences**. Numbered versions are fixed and will never change. The currently supported versions are:
| version | definition |
|----------|-----------
|"default" | Currently "20140601".
|"20200207" | RSA-PSS, RSA-RSAE, RSA-PKCS1, and ECDSA. SHA1 allowed, but only as a fallback.
|"20140601" | RSA-PKCS1 and ECDSA. SHA1 allowed, but only as a fallback.
### s2n\_config\_set\_ecc\_preferences
```c
int s2n_config_set_ecc_preferences(struct s2n_config *config,
const char *version);
```

**s2n_config_set_ecc_preferences** sets the list of acceptable ecc curves in descending order of preference.

The "default" version behaves as in **s2n_config_set_cipher_preferences**. Numbered versions are fixed and will never change. The currently supported versions are:

| version | definition |
|----------|-----------
|"default" | Currently "20140601".
|"20200310" | Curves x25519, secp256r1, and secp384r1.
|"20140601" | Curves secp256r1 and secp384r1.

### s2n\_config\_add\_cert\_chain\_and\_key

```c
Expand Down
Loading

0 comments on commit f3abfab

Please sign in to comment.