int s2n_connection_get_alert(struct s2n_connection *conn) { if (s2n_stuffer_data_available(&conn->alert_in) != 2) { S2N_ERROR(S2N_ERR_NO_ALERT); } uint8_t alert_code = 0; GUARD(s2n_stuffer_read_uint8(&conn->alert_in, &alert_code)); GUARD(s2n_stuffer_read_uint8(&conn->alert_in, &alert_code)); return alert_code; }
int s2n_client_ccs_recv(struct s2n_connection *conn) { uint8_t type; GUARD(s2n_prf_client_finished(conn)); struct s2n_blob seq = {.data = conn->secure.client_sequence_number,.size = sizeof(conn->secure.client_sequence_number) }; GUARD(s2n_blob_zero(&seq)); /* Update the client to use the cipher-suite */ conn->client = &conn->secure; GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type)); S2N_ERROR_IF(type != CHANGE_CIPHER_SPEC_TYPE, S2N_ERR_BAD_MESSAGE); /* Flush any partial alert messages that were pending */ GUARD(s2n_stuffer_wipe(&conn->alert_in)); return 0; } int s2n_client_ccs_send(struct s2n_connection *conn) { GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, CHANGE_CIPHER_SPEC_TYPE)); return 0; }
int s2n_kem_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, union s2n_kex_raw_server_data *raw_server_data) { struct s2n_kem_raw_server_params *kem_data = &raw_server_data->kem_data; struct s2n_stuffer *in = &conn->handshake.io; const struct s2n_kem *kem = conn->secure.s2n_kem_keys.negotiated_kem; kem_public_key_size key_length; /* Keep a copy to the start of the whole structure for the signature check */ data_to_verify->data = s2n_stuffer_raw_read(in, 0); notnull_check(data_to_verify->data); /* the server sends the KEM ID again and this must match what was agreed upon during server hello */ kem_extension_size kem_id; GUARD(s2n_stuffer_read_uint8(in, &kem_id)); eq_check(kem_id, kem->kem_extension_id); GUARD(s2n_stuffer_read_uint16(in, &key_length)); S2N_ERROR_IF(key_length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE); S2N_ERROR_IF(key_length != conn->secure.s2n_kem_keys.negotiated_kem->public_key_length, S2N_ERR_BAD_MESSAGE); kem_data->raw_public_key.data = s2n_stuffer_raw_read(in, key_length); notnull_check(kem_data->raw_public_key.data); kem_data->raw_public_key.size = key_length; data_to_verify->size = sizeof(kem_extension_size) + sizeof(kem_public_key_size) + key_length; return 0; }
int main(int argc, char **argv) { uint8_t u8; uint16_t u16; uint32_t u32; uint32_t stuffer_size = nondet_uint32(); __CPROVER_assume(stuffer_size > 0); uint32_t entropy_size = nondet_uint32(); __CPROVER_assume(entropy_size > 0); uint8_t entropy[entropy_size]; struct s2n_stuffer stuffer; GUARD(s2n_stuffer_alloc(&stuffer, stuffer_size)); struct s2n_blob in = {.data = entropy,.size = entropy_size}; GUARD(s2n_stuffer_write(&stuffer, &in)); GUARD(s2n_stuffer_wipe(&stuffer)); while(nondet_bool()) { GUARD(s2n_stuffer_write_uint8(&stuffer, nondet_uint64())); } while(nondet_bool()) { GUARD(s2n_stuffer_read_uint8(&stuffer, &u8)); } GUARD(s2n_stuffer_wipe(&stuffer)); while(nondet_bool()) { GUARD(s2n_stuffer_write_uint16(&stuffer, nondet_uint64())); } while(nondet_bool()) { GUARD(s2n_stuffer_read_uint16(&stuffer, &u16)); } GUARD(s2n_stuffer_wipe(&stuffer)); while(nondet_bool()) { GUARD(s2n_stuffer_write_uint24(&stuffer, nondet_uint64())); } while(nondet_bool()) { GUARD(s2n_stuffer_read_uint24(&stuffer, &u32)); } GUARD(s2n_stuffer_wipe(&stuffer)); while(nondet_bool()) { GUARD(s2n_stuffer_write_uint32(&stuffer, nondet_uint64())); } while(nondet_bool()) { GUARD(s2n_stuffer_read_uint32(&stuffer, &u32)); } GUARD(s2n_stuffer_free(&stuffer)); }
int s2n_stuffer_write_hex(struct s2n_stuffer *stuffer, struct s2n_stuffer *in, uint32_t n) { gte_check(s2n_stuffer_space_remaining(stuffer), n * 2); for (int i = 0; i < n; i++) { uint8_t c; GUARD(s2n_stuffer_read_uint8(in, &c)); GUARD(s2n_stuffer_write_uint8_hex(stuffer, c)); } return 0; }
static int s2n_recv_client_renegotiation_info(struct s2n_connection *conn, struct s2n_stuffer *extension) { /* RFC5746 Section 3.2: The renegotiated_connection field is of zero length for the initial handshake. */ uint8_t renegotiated_connection_len; GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len)); if (s2n_stuffer_data_available(extension) || renegotiated_connection_len) { S2N_ERROR(S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO); } conn->secure_renegotiation = 1; return 0; }
int s2n_handshake_parse_header(struct s2n_connection *conn, uint8_t * message_type, uint32_t * length) { if (s2n_stuffer_data_available(&conn->handshake.io) < TLS_HANDSHAKE_HEADER_LENGTH) { S2N_ERROR(S2N_ERR_SIZE_MISMATCH); } /* read the message header */ GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, message_type)); GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, length)); return 0; }
static int s2n_recv_client_max_frag_len(struct s2n_connection *conn, struct s2n_stuffer *extension) { if (!conn->config->accept_mfl) { return 0; } uint8_t mfl_code; GUARD(s2n_stuffer_read_uint8(extension, &mfl_code)); if (mfl_code > S2N_TLS_MAX_FRAG_LEN_4096 || mfl_code_to_length[mfl_code] > S2N_TLS_MAXIMUM_FRAGMENT_LENGTH) { return 0; } conn->mfl_code = mfl_code; conn->max_outgoing_fragment_length = mfl_code_to_length[mfl_code]; return 0; }
int s2n_server_status_recv(struct s2n_connection *conn) { uint8_t type; struct s2n_blob status = { .data = NULL, .size = 0 }; GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type)); GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, &status.size)); status.data = s2n_stuffer_raw_read(&conn->handshake.io, status.size); notnull_check(status.data); if (type == S2N_STATUS_REQUEST_OCSP) { GUARD(s2n_alloc(&conn->status_response, status.size)); memcpy_check(conn->status_response.data, status.data, status.size); conn->status_response.size = status.size; } return 0; }
int s2n_recv_server_alpn(struct s2n_connection *conn, struct s2n_stuffer *extension) { uint16_t size_of_all; GUARD(s2n_stuffer_read_uint16(extension, &size_of_all)); if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all < 3) { /* ignore invalid extension size */ return 0; } uint8_t protocol_len; GUARD(s2n_stuffer_read_uint8(extension, &protocol_len)); uint8_t *protocol = s2n_stuffer_raw_read(extension, protocol_len); notnull_check(protocol); /* copy the first protocol name */ memcpy_check(conn->application_protocol, protocol, protocol_len); conn->application_protocol[protocol_len] = '\0'; return 0; }
static int s2n_recv_client_server_name(struct s2n_connection *conn, struct s2n_stuffer *extension) { uint16_t size_of_all; uint8_t server_name_type; uint16_t server_name_len; uint8_t *server_name; GUARD(s2n_stuffer_read_uint16(extension, &size_of_all)); if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all < 3) { /* the size of all server names is incorrect, ignore the extension */ return 0; } GUARD(s2n_stuffer_read_uint8(extension, &server_name_type)); if (server_name_type != 0) { /* unknown server name type, ignore the extension */ return 0; } GUARD(s2n_stuffer_read_uint16(extension, &server_name_len)); if (server_name_len + 3 > size_of_all) { /* the server name length is incorrect, ignore the extension */ return 0; } if (server_name_len > sizeof(conn->server_name) - 1) { /* the server name is too long, ignore the extension */ return 0; } notnull_check(server_name = s2n_stuffer_raw_read(extension, server_name_len)); /* copy the first server name */ memcpy_check(conn->server_name, server_name, server_name_len); return 0; }
int s2n_server_status_recv(struct s2n_connection *conn) { uint8_t type; struct s2n_blob status = { .data = NULL, .size = 0 }; GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type)); GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, &status.size)); status.data = s2n_stuffer_raw_read(&conn->handshake.io, status.size); notnull_check(status.data); if (type == S2N_STATUS_REQUEST_OCSP) { GUARD(s2n_alloc(&conn->status_response, status.size)); memcpy_check(conn->status_response.data, status.data, status.size); conn->status_response.size = status.size; } conn->handshake.next_state = SERVER_HELLO_DONE; if (conn->pending.cipher_suite->key_exchange_alg->flags & S2N_KEY_EXCHANGE_EPH) { conn->handshake.next_state = SERVER_KEY; } return 0; }
static int s2n_ecdhe_server_key_recv(struct s2n_connection *conn) { struct s2n_hash_state signature_hash; struct s2n_stuffer *in = &conn->handshake.io; struct s2n_blob ecdhparams; struct s2n_blob signature; uint16_t signature_length; /* Read server ECDH params and calculate their hash */ GUARD(s2n_ecc_read_ecc_params(&conn->secure.server_ecc_params, in, &ecdhparams)); GUARD(s2n_hash_init(&signature_hash, conn->secure.signature_digest_alg)); if (conn->actual_protocol_version == S2N_TLS12) { uint8_t hash_algorithm; uint8_t signature_algorithm; GUARD(s2n_stuffer_read_uint8(in, &hash_algorithm)); GUARD(s2n_stuffer_read_uint8(in, &signature_algorithm)); if (signature_algorithm != TLS_SIGNATURE_ALGORITHM_RSA) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } switch(hash_algorithm) { case TLS_HASH_ALGORITHM_MD5: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_MD5)); break; case TLS_HASH_ALGORITHM_SHA1: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA1)); break; case TLS_HASH_ALGORITHM_SHA224: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA224)); break; case TLS_HASH_ALGORITHM_SHA256: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA256)); break; case TLS_HASH_ALGORITHM_SHA384: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA384)); break; case TLS_HASH_ALGORITHM_SHA512: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA512)); break; default: S2N_ERROR(S2N_ERR_BAD_MESSAGE); } } GUARD(s2n_hash_update(&signature_hash, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN)); GUARD(s2n_hash_update(&signature_hash, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN)); GUARD(s2n_hash_update(&signature_hash, ecdhparams.data, ecdhparams.size)); /* Verify the signature */ GUARD(s2n_stuffer_read_uint16(in, &signature_length)); signature.size = signature_length; signature.data = s2n_stuffer_raw_read(in, signature.size); notnull_check(signature.data); gt_check(signature_length, 0); if (s2n_rsa_verify(&conn->secure.server_rsa_public_key, &signature_hash, &signature) < 0) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } /* We don't need the key any more, so free it */ GUARD(s2n_rsa_public_key_free(&conn->secure.server_rsa_public_key)); return 0; }
static int s2n_dhe_server_key_recv(struct s2n_connection *conn) { struct s2n_hash_state signature_hash; struct s2n_stuffer *in = &conn->handshake.io; struct s2n_blob p, g, Ys, serverDHparams, signature; uint16_t p_length; uint16_t g_length; uint16_t Ys_length; uint16_t signature_length; /* Keep a copy to the start of the whole structure for the signature check */ serverDHparams.data = s2n_stuffer_raw_read(in, 0); notnull_check(serverDHparams.data); /* Read each of the three elements in */ GUARD(s2n_stuffer_read_uint16(in, &p_length)); p.size = p_length; p.data = s2n_stuffer_raw_read(in, p.size); notnull_check(p.data); GUARD(s2n_stuffer_read_uint16(in, &g_length)); g.size = g_length; g.data = s2n_stuffer_raw_read(in, g.size); notnull_check(g.data); GUARD(s2n_stuffer_read_uint16(in, &Ys_length)); Ys.size = Ys_length; Ys.data = s2n_stuffer_raw_read(in, Ys.size); notnull_check(Ys.data); /* Now we know the total size of the structure */ serverDHparams.size = 2 + p_length + 2 + g_length + 2 + Ys_length; GUARD(s2n_hash_init(&signature_hash, conn->secure.signature_digest_alg)); if (conn->actual_protocol_version == S2N_TLS12) { uint8_t hash_algorithm; uint8_t signature_algorithm; GUARD(s2n_stuffer_read_uint8(in, &hash_algorithm)); GUARD(s2n_stuffer_read_uint8(in, &signature_algorithm)); if (signature_algorithm != TLS_SIGNATURE_ALGORITHM_RSA) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } switch(hash_algorithm) { case TLS_HASH_ALGORITHM_MD5: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_MD5)); break; case TLS_HASH_ALGORITHM_SHA1: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA1)); break; case TLS_HASH_ALGORITHM_SHA224: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA224)); break; case TLS_HASH_ALGORITHM_SHA256: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA256)); break; case TLS_HASH_ALGORITHM_SHA384: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA384)); break; case TLS_HASH_ALGORITHM_SHA512: GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA512)); break; default: S2N_ERROR(S2N_ERR_BAD_MESSAGE); } } GUARD(s2n_hash_update(&signature_hash, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN)); GUARD(s2n_hash_update(&signature_hash, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN)); GUARD(s2n_hash_update(&signature_hash, serverDHparams.data, serverDHparams.size)); GUARD(s2n_stuffer_read_uint16(in, &signature_length)); signature.size = signature_length; signature.data = s2n_stuffer_raw_read(in, signature.size); notnull_check(signature.data); gt_check(signature_length, 0); if (s2n_rsa_verify(&conn->secure.server_rsa_public_key, &signature_hash, &signature) < 0) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } /* We don't need the key any more, so free it */ GUARD(s2n_rsa_public_key_free(&conn->secure.server_rsa_public_key)); /* Copy the DH details */ GUARD(s2n_dh_p_g_Ys_to_dh_params(&conn->secure.server_dh_params, &p, &g, &Ys)); return 0; }
int s2n_server_hello_recv(struct s2n_connection *conn) { struct s2n_stuffer *in = &conn->handshake.io; uint8_t compression_method; uint8_t session_id[S2N_TLS_SESSION_ID_LEN]; uint8_t session_id_len; uint16_t extensions_size; uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN)); conn->server_protocol_version = (protocol_version[0] * 10) + protocol_version[1]; if (conn->server_protocol_version > conn->actual_protocol_version) { GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn)); S2N_ERROR(S2N_ERR_BAD_MESSAGE); } conn->actual_protocol_version = conn->server_protocol_version; conn->actual_protocol_version_established = 1; /* Verify that the protocol version is sane */ if (conn->actual_protocol_version < S2N_SSLv3 || conn->actual_protocol_version > S2N_TLS12) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } conn->pending.signature_digest_alg = S2N_HASH_MD5_SHA1; if (conn->actual_protocol_version == S2N_TLS12) { conn->pending.signature_digest_alg = S2N_HASH_SHA1; } GUARD(s2n_stuffer_read_bytes(in, conn->pending.server_random, S2N_TLS_RANDOM_DATA_LEN)); GUARD(s2n_stuffer_read_uint8(in, &session_id_len)); if (session_id_len > S2N_TLS_SESSION_ID_LEN) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } GUARD(s2n_stuffer_read_bytes(in, session_id, session_id_len)); uint8_t *cipher_suite_wire = s2n_stuffer_raw_read(in, S2N_TLS_CIPHER_SUITE_LEN); notnull_check(cipher_suite_wire); GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire)); GUARD(s2n_stuffer_read_uint8(in, &compression_method)); if (compression_method != S2N_TLS_COMPRESSION_METHOD_NULL) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } if (s2n_stuffer_data_available(in) < 2) { GUARD(s2n_conn_set_handshake_type(conn)); /* No extensions */ return 0; } GUARD(s2n_stuffer_read_uint16(in, &extensions_size)); if (extensions_size > s2n_stuffer_data_available(in)) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } struct s2n_blob extensions; extensions.size = extensions_size; extensions.data = s2n_stuffer_raw_read(in, extensions.size); GUARD(s2n_server_extensions_recv(conn, &extensions)); GUARD(s2n_conn_set_handshake_type(conn)); return 0; }
int s2n_client_hello_recv(struct s2n_connection *conn) { struct s2n_stuffer *in = &conn->handshake.io; uint8_t compression_methods; uint16_t extensions_size; uint16_t cipher_suites_length; uint8_t *cipher_suites; uint8_t client_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; GUARD(s2n_stuffer_read_bytes(in, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN)); GUARD(s2n_stuffer_read_bytes(in, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN)); GUARD(s2n_stuffer_read_uint8(in, &conn->session_id_len)); conn->client_protocol_version = (client_protocol_version[0] * 10) + client_protocol_version[1]; if (conn->client_protocol_version < conn->config->cipher_preferences->minimum_protocol_version || conn->client_protocol_version > conn->server_protocol_version) { GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn)); S2N_ERROR(S2N_ERR_BAD_MESSAGE); } conn->client_hello_version = conn->client_protocol_version; conn->actual_protocol_version = MIN(conn->client_protocol_version, conn->server_protocol_version); if (conn->session_id_len > S2N_TLS_SESSION_ID_MAX_LEN || conn->session_id_len > s2n_stuffer_data_available(in)) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } GUARD(s2n_stuffer_read_bytes(in, conn->session_id, conn->session_id_len)); GUARD(s2n_stuffer_read_uint16(in, &cipher_suites_length)); if (cipher_suites_length % S2N_TLS_CIPHER_SUITE_LEN) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } cipher_suites = s2n_stuffer_raw_read(in, cipher_suites_length); notnull_check(cipher_suites); /* Don't choose the cipher yet, read the extensions first */ GUARD(s2n_stuffer_read_uint8(in, &compression_methods)); GUARD(s2n_stuffer_skip_read(in, compression_methods)); /* This is going to be our default if the client has no preference. */ conn->secure.server_ecc_params.negotiated_curve = &s2n_ecc_supported_curves[0]; if (s2n_stuffer_data_available(in) >= 2) { /* Read extensions if they are present */ GUARD(s2n_stuffer_read_uint16(in, &extensions_size)); if (extensions_size > s2n_stuffer_data_available(in)) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } struct s2n_blob extensions; extensions.size = extensions_size; extensions.data = s2n_stuffer_raw_read(in, extensions.size); notnull_check(extensions.data); GUARD(s2n_client_extensions_recv(conn, &extensions)); } /* Now choose the ciphers and the cert chain. */ GUARD(s2n_set_cipher_as_tls_server(conn, cipher_suites, cipher_suites_length / 2)); conn->server->chosen_cert_chain = conn->config->cert_and_key_pairs; /* Set the handshake type */ GUARD(s2n_conn_set_handshake_type(conn)); return 0; }
static int s2n_recv_client_alpn(struct s2n_connection *conn, struct s2n_stuffer *extension) { uint16_t size_of_all; struct s2n_stuffer client_protos; struct s2n_stuffer server_protos; if (!conn->config->application_protocols.size) { /* No protocols configured, nothing to do */ return 0; } GUARD(s2n_stuffer_read_uint16(extension, &size_of_all)); if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all < 3) { /* Malformed length, ignore the extension */ return 0; } struct s2n_blob application_protocols = { .data = s2n_stuffer_raw_read(extension, size_of_all), .size = size_of_all }; notnull_check(application_protocols.data); /* Find a matching protocol */ GUARD(s2n_stuffer_init(&client_protos, &application_protocols)); GUARD(s2n_stuffer_write(&client_protos, &application_protocols)); GUARD(s2n_stuffer_init(&server_protos, &conn->config->application_protocols)); GUARD(s2n_stuffer_write(&server_protos, &conn->config->application_protocols)); while (s2n_stuffer_data_available(&server_protos)) { uint8_t length; uint8_t protocol[255]; GUARD(s2n_stuffer_read_uint8(&server_protos, &length)); GUARD(s2n_stuffer_read_bytes(&server_protos, protocol, length)); while (s2n_stuffer_data_available(&client_protos)) { uint8_t client_length; GUARD(s2n_stuffer_read_uint8(&client_protos, &client_length)); if (client_length > s2n_stuffer_data_available(&client_protos)) { S2N_ERROR(S2N_ERR_BAD_MESSAGE); } if (client_length != length) { GUARD(s2n_stuffer_skip_read(&client_protos, client_length)); } else { uint8_t client_protocol[255]; GUARD(s2n_stuffer_read_bytes(&client_protos, client_protocol, client_length)); if (memcmp(client_protocol, protocol, client_length) == 0) { memcpy_check(conn->application_protocol, client_protocol, client_length); conn->application_protocol[client_length] = '\0'; return 0; } } } GUARD(s2n_stuffer_reread(&client_protos)); } S2N_ERROR(S2N_ERR_NO_APPLICATION_PROTOCOL); } static int s2n_recv_client_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension) { if (s2n_stuffer_data_available(extension) < 5) { /* Malformed length, ignore the extension */ return 0; } uint8_t type; GUARD(s2n_stuffer_read_uint8(extension, &type)); if (type != (uint8_t) S2N_STATUS_REQUEST_OCSP) { /* We only support OCSP (type 1), ignore the extension */ return 0; } conn->status_type = (s2n_status_request_type) type; return 0; } static int s2n_recv_client_elliptic_curves(struct s2n_connection *conn, struct s2n_stuffer *extension) { uint16_t size_of_all; struct s2n_blob proposed_curves; GUARD(s2n_stuffer_read_uint16(extension, &size_of_all)); if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all % 2) { /* Malformed length, ignore the extension */ return 0; } proposed_curves.size = size_of_all; proposed_curves.data = s2n_stuffer_raw_read(extension, proposed_curves.size); notnull_check(proposed_curves.data); if (s2n_ecc_find_supported_curve(&proposed_curves, &conn->secure.server_ecc_params.negotiated_curve) != 0) { /* Can't agree on a curve, ECC is not allowed. Return success to proceed with the handshake. */ conn->secure.server_ecc_params.negotiated_curve = NULL; } return 0; }