struct s2n_connection *s2n_connection_new(s2n_mode mode) { struct s2n_blob blob; struct s2n_connection *conn; GUARD_PTR(s2n_alloc(&blob, sizeof(struct s2n_connection))); GUARD_PTR(s2n_blob_zero(&blob)); if (mode == S2N_CLIENT) { /* At present s2n is not suitable for use in client mode, as it * does not perform any certificate validation. However it is useful * to use S2N in client mode for testing purposes. An environment * variable is required to be set for the client mode to work. */ if (getenv("S2N_ENABLE_CLIENT_MODE") == NULL) { s2n_free(&blob); S2N_ERROR_PTR(S2N_ERR_CLIENT_MODE_DISABLED); } } /* Cast 'through' void to acknowledge that we are changing alignment, * which is ok, as blob.data is always aligned. */ conn = (struct s2n_connection *)(void *)blob.data; conn->mode = mode; conn->blinding = S2N_BUILT_IN_BLINDING; conn->config = &s2n_default_config; /* Allocate the fixed-size stuffers */ blob.data = conn->alert_in_data; blob.size = S2N_ALERT_LENGTH; GUARD_PTR(s2n_stuffer_init(&conn->alert_in, &blob)); blob.data = conn->reader_alert_out_data; blob.size = S2N_ALERT_LENGTH; GUARD_PTR(s2n_stuffer_init(&conn->reader_alert_out, &blob)); blob.data = conn->writer_alert_out_data; blob.size = S2N_ALERT_LENGTH; GUARD_PTR(s2n_stuffer_init(&conn->writer_alert_out, &blob)); GUARD_PTR(s2n_stuffer_alloc(&conn->out, S2N_DEFAULT_RECORD_LENGTH)); /* Initialize the growable stuffers. Zero length at first, but the resize * in _wipe will fix that */ blob.data = conn->header_in_data; blob.size = S2N_TLS_RECORD_HEADER_LENGTH; GUARD_PTR(s2n_stuffer_init(&conn->header_in, &blob)); GUARD_PTR(s2n_stuffer_growable_alloc(&conn->in, 0)); GUARD_PTR(s2n_stuffer_growable_alloc(&conn->handshake.io, 0)); GUARD_PTR(s2n_connection_wipe(conn)); return conn; }
void *s2n_stuffer_raw_write(struct s2n_stuffer *stuffer, const uint32_t data_len) { GUARD_PTR(s2n_stuffer_skip_write(stuffer, data_len)); stuffer->tainted = 1; return stuffer->blob.data + stuffer->write_cursor - data_len; }
void *s2n_stuffer_raw_read(struct s2n_stuffer *stuffer, uint32_t data_len) { GUARD_PTR(s2n_stuffer_skip_read(stuffer, data_len)); stuffer->tainted = 1; return stuffer->blob.data + stuffer->read_cursor - data_len; }
struct s2n_map *s2n_map_new() { struct s2n_blob mem; struct s2n_map *map; GUARD_PTR(s2n_alloc(&mem, sizeof(struct s2n_map))); map = (void *) mem.data; map->capacity = 0; map->size = 0; map->immutable = 0; map->table = NULL; GUARD_PTR(s2n_map_embiggen(map, S2N_INITIAL_TABLE_SIZE)); return map; }
struct s2n_config *s2n_config_new(void) { struct s2n_blob allocator; struct s2n_config *new_config; GUARD_PTR(s2n_alloc(&allocator, sizeof(struct s2n_config))); new_config = (struct s2n_config *)(void *)allocator.data; new_config->cert_and_key_pairs = NULL; new_config->dhparams = NULL; new_config->application_protocols.data = NULL; new_config->application_protocols.size = 0; new_config->status_request_type = S2N_STATUS_REQUEST_NONE; new_config->nanoseconds_since_epoch = get_nanoseconds_since_epoch; GUARD_PTR(s2n_config_set_cipher_preferences(new_config, "default")); return new_config; }
static struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, struct s2n_cipher_suite *cipher_suite) { for (int i = 0; i < conn->config->num_certificates; i++) { struct s2n_cert_chain_and_key *cert_chain_and_key = conn->config->cert_and_key_pairs[i]; struct s2n_cert *leaf_cert = cert_chain_and_key->cert_chain->head; uint8_t cert_compatibility = 0; GUARD_PTR(s2n_cipher_is_compatible_with_cert(cipher_suite, leaf_cert, &cert_compatibility)); if (cert_compatibility) { return cert_chain_and_key; } } return NULL; }