int s2n_connection_kill(struct s2n_connection *conn) { conn->closed = 1; /* Delay between 10 and 30 seconds in nanoseconds */ int64_t min = TEN_S, max = 3 * TEN_S; /* Keep track of the delay so that it can be enforced */ conn->delay = min + s2n_public_random(max - min); /* Restart the write timer */ GUARD(s2n_timer_start(conn->config, &conn->write_timer)); if (conn->blinding == S2N_BUILT_IN_BLINDING) { struct timespec sleep_time = { .tv_sec = conn->delay / ONE_S, .tv_nsec = conn->delay % ONE_S }; int r; do { r = nanosleep(&sleep_time, &sleep_time); } while (r != 0); } return 0; } const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t *length) { if (!length) { return NULL; } *length = conn->status_response.size; return conn->status_response.data; }
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)); GUARD_PTR(s2n_timer_start(conn->config, &conn->write_timer)); return conn; }
int main(int argc, char **argv) { struct s2n_timer timer; uint64_t nanoseconds; BEGIN_TEST(); /* First: Perform some tests using the real clock */ EXPECT_SUCCESS(s2n_timer_start(&timer)); EXPECT_SUCCESS(s2n_timer_reset(&timer, &nanoseconds)); EXPECT_TRUE(nanoseconds < 1000000000); EXPECT_SUCCESS(s2n_timer_elapsed(&timer, &nanoseconds)); EXPECT_TRUE(nanoseconds < 1000000000); EXPECT_SUCCESS(sleep(1)); EXPECT_SUCCESS(s2n_timer_reset(&timer, &nanoseconds)); EXPECT_TRUE(nanoseconds > 1000000000); EXPECT_TRUE(nanoseconds < 2000000000); EXPECT_SUCCESS(sleep(1)); EXPECT_SUCCESS(s2n_timer_elapsed(&timer, &nanoseconds)); EXPECT_TRUE(nanoseconds > 1000000000); EXPECT_TRUE(nanoseconds < 2000000000); #if !defined(__APPLE__) || !defined(__MACH__) /* Next: perform some tests around timespec boundaries */ /* Pretend that there were 999,999,999 nanoseconds elapsed in the * previously measured instant. Keep reseting the timer until * the second progresses from that instant, and there are also * less than 999,999,999 nanoseconds elapsed. * * This sets up a situation in which the tv_sec field causes time * to move "forwards", and tv_nsec causes it to move backwards. * e.g. * * previous_time = 10 * * timer.time.tv_sec = 11 * timer.time.tv_nsec = 123456789; * * delta will be: * (11 - 10) * 1000000000 * + (123456789 - 999999999) * * = 123456790 (same as 1 + 123456789) */ time_t previous_time; do { previous_time = timer.time.tv_sec; timer.time.tv_nsec = 999999999; EXPECT_SUCCESS(s2n_timer_reset(&timer, &nanoseconds)); } while(previous_time != (timer.time.tv_sec - 1) || timer.time.tv_nsec == 999999999); EXPECT_TRUE(nanoseconds < 1000000000); EXPECT_TRUE(nanoseconds == 1 + timer.time.tv_nsec); /* Now we perform the oppossite test: make sure that the previous value for * nsec is smaller than the later one */ do { previous_time = timer.time.tv_sec; timer.time.tv_nsec = 0; EXPECT_SUCCESS(s2n_timer_reset(&timer, &nanoseconds)); } while(previous_time != (timer.time.tv_sec - 1) || timer.time.tv_nsec == 0); EXPECT_TRUE(nanoseconds > 1000000000); EXPECT_TRUE(nanoseconds < 2000000000); EXPECT_TRUE(nanoseconds == 1000000000 + timer.time.tv_nsec); #endif END_TEST(); }
int main(int argc, char **argv) { uint8_t data[256] = { 0 }; struct s2n_drbg drbg = {{ 0 }}; struct s2n_blob blob = {.data = data, .size = 64 }; struct s2n_timer timer; uint64_t drbg_nanoseconds; uint64_t urandom_nanoseconds; struct s2n_stuffer nist_reference_personalization_strings; struct s2n_stuffer nist_reference_returned_bits; struct s2n_stuffer nist_reference_values; struct s2n_config *config; BEGIN_TEST(); EXPECT_NOT_NULL(config = s2n_config_new()) /* Open /dev/urandom */ EXPECT_TRUE(entropy_fd = open("/dev/urandom", O_RDONLY)); /* Convert the hex entropy data into binary */ EXPECT_SUCCESS(s2n_stuffer_alloc_ro_from_hex_string(&nist_reference_entropy, nist_reference_entropy_hex)); EXPECT_SUCCESS(s2n_stuffer_alloc_ro_from_hex_string(&nist_reference_personalization_strings, nist_reference_personalization_strings_hex)); EXPECT_SUCCESS(s2n_stuffer_alloc_ro_from_hex_string(&nist_reference_returned_bits, nist_reference_returned_bits_hex)); EXPECT_SUCCESS(s2n_stuffer_alloc_ro_from_hex_string(&nist_reference_values, nist_reference_values_hex)); /* Check everything against the NIST vectors */ for (int i = 0; i < 14; i++) { uint8_t ps[32]; struct s2n_drbg nist_drbg = { .entropy_generator = nist_fake_urandom_data }; struct s2n_blob personalization_string = {.data = ps, .size = 32}; /* Read the next personalization string */ EXPECT_SUCCESS(s2n_stuffer_read(&nist_reference_personalization_strings, &personalization_string)); /* Instantiate the DRBG */ EXPECT_SUCCESS(s2n_drbg_instantiate(&nist_drbg, &personalization_string)); uint8_t nist_v[16]; GUARD(s2n_stuffer_read_bytes(&nist_reference_values, nist_v, sizeof(nist_v))); EXPECT_TRUE(memcmp(nist_v, nist_drbg.v, sizeof(nist_drbg.v)) == 0); /* Generate 512 bits (FIRST CALL) */ uint8_t out[64]; struct s2n_blob generated = {.data = out, .size = 64 }; EXPECT_SUCCESS(s2n_drbg_generate(&nist_drbg, &generated)); GUARD(s2n_stuffer_read_bytes(&nist_reference_values, nist_v, sizeof(nist_v))); EXPECT_TRUE(memcmp(nist_v, nist_drbg.v, sizeof(nist_drbg.v)) == 0); /* Generate another 512 bits (SECOND CALL) */ EXPECT_SUCCESS(s2n_drbg_generate(&nist_drbg, &generated)); GUARD(s2n_stuffer_read_bytes(&nist_reference_values, nist_v, sizeof(nist_v))); EXPECT_TRUE(memcmp(nist_v, nist_drbg.v, sizeof(nist_drbg.v)) == 0); uint8_t nist_returned_bits[64]; GUARD(s2n_stuffer_read_bytes(&nist_reference_returned_bits, nist_returned_bits, sizeof(nist_returned_bits))); EXPECT_TRUE(memcmp(nist_returned_bits, out, sizeof(nist_returned_bits)) == 0); EXPECT_SUCCESS(s2n_drbg_wipe(&nist_drbg)); } EXPECT_SUCCESS(s2n_drbg_instantiate(&drbg, &blob)); /* Use the DRBG for 32MB of data */ EXPECT_SUCCESS(s2n_timer_start(config, &timer)); for (int i = 0; i < 500000; i++) { EXPECT_SUCCESS(s2n_drbg_generate(&drbg, &blob)); } EXPECT_SUCCESS(s2n_timer_reset(config, &timer, &drbg_nanoseconds)); /* Use urandom for 32MB of data */ EXPECT_SUCCESS(s2n_timer_start(config, &timer)); for (int i = 0; i < 500000; i++) { EXPECT_SUCCESS(s2n_get_urandom_data(&blob)); } EXPECT_SUCCESS(s2n_timer_reset(config, &timer, &urandom_nanoseconds)); /* Confirm that the DRBG is faster than urandom */ EXPECT_TRUE(drbg_nanoseconds < urandom_nanoseconds); /* NOTE: s2n_random_test also includes monobit tests for this DRBG */ /* the DRBG state is 128 bytes, test that we can get more than that */ blob.size = 129; for (int i = 0; i < 10; i++) { EXPECT_SUCCESS(s2n_drbg_generate(&drbg, &blob)); } EXPECT_SUCCESS(s2n_drbg_wipe(&drbg)); EXPECT_SUCCESS(s2n_stuffer_free(&nist_reference_entropy)); EXPECT_SUCCESS(s2n_stuffer_free(&nist_reference_personalization_strings)); EXPECT_SUCCESS(s2n_stuffer_free(&nist_reference_returned_bits)); EXPECT_SUCCESS(s2n_stuffer_free(&nist_reference_values)); END_TEST(); }